maptalks+three.js+vue webpack实现二维地图上贴三维模型操作


Posted in Javascript onAugust 10, 2020

我们不是走在坑里就是走在前往坑的路上_(:з?∠)_

最终效果如图:(地图上添加一个“三维地图”的toolbar按钮,点击后在二维地图上贴上建好的三维模型点击显示弹框)

maptalks+three.js+vue webpack实现二维地图上贴三维模型操作

以下都在已经引入并且初始化maptalks地图的基础上,如何引入使用maptalks可以查看以下文章

1、安装maptalks.three包

npm install maptalks.three

2、安装three包

npm install three

3、安装obj-loader和mtl-loader包

npm i --save three-obj-mtl-loader

4、引入model模型文件到public下(放在这里是因为打包后读取路径问题,目前发现放在这里才能在打包后正确读取)

maptalks+three.js+vue webpack实现二维地图上贴三维模型操作

5、Vue页面代码

引入包

import * as THREE from 'three'
import * as maptalks from 'maptalks'
import { ThreeLayer } from 'maptalks.three'
import { MTLLoader, OBJLoader } from 'three-obj-mtl-loader'

初始化的地图对象是

this.map

下面是渲染三维模型的方法

// 渲染三维
draw3D() {
 const that = this
 // 三维地图
 var three_flag = false
 // ///单体化交互开始
 var INTERSECTED
 this.map.on('click', function(e) {
  //  console.log(e)
  var raycaster = new THREE.Raycaster()
  var mouse = new THREE.Vector2()
  const camera = threeLayer.getCamera()
  const scene = threeLayer.getScene()
  if (!scene) return
 
  const size = that.map.getSize()
  const width = size.width; const height = size.height
  mouse.x = (e.containerPoint.x / width) * 2 - 1
  mouse.y = -((e.containerPoint.y) / height) * 2 + 1
 
  raycaster.setFromCamera(mouse, camera)
  raycaster.linePrecision = 3
 
  var intersects = raycaster.intersectObjects(scene.children, true)
  // var intersects = raycaster.intersectObject(points);
  if (!intersects) return
  if (Array.isArray(intersects) && intersects.length === 0) return
  console.log(intersects)
  // 这里我们操作第一个相交的物体
  if (intersects.length > 0) {
   if (INTERSECTED != intersects[0].object) {
    if (INTERSECTED) {
     // INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
     // INTERSECTED.scale.set(1,1,1);
     if (INTERSECTED.material.length === undefined) {
      INTERSECTED.material.color.setHex(INTERSECTED.currentHex)
     } else {
      for (var i = 0; i < INTERSECTED.material.length; i++) {
       INTERSECTED.material[i].color.setHex(INTERSECTED.currentHex)
      }
     }
    }
    INTERSECTED = intersects[0].object
 
    // 设置相交的第一个物体的颜色
    // INTERSECTED.currentHex = INTERSECTED.material[0].color.getHex();
    INTERSECTED.currentHex = 16777215
    // 将该物体设为随机的其他颜色
    // INTERSECTED.material.opacity = 0.2;
 
    // INTERSECTED.material.transparent = true;
    // INTERSECTED.material.opacity = 0.2;
    // INTERSECTED.material.needsUpdate = true;
    // INTERSECTED.material.transparent = false;
 
    // INTERSECTED.material.color.setHex(0xff0000);
    if (INTERSECTED.material.length === undefined) {
     INTERSECTED.material.color.setHex(0x1E90FF)
    } else {
     for (var i = 0; i < INTERSECTED.material.length; i++) {
      INTERSECTED.material[i].color.setHex(0x1E90FF)
     }
    }
   }
   // //////////////
   var lonlat = e.coordinate
   if (true) {
    var options = {
     'autoOpenOn': 'null', // set to null if not to open window when clicking on map
     'single': true,
     'width': 410,
     'height': 190,
     'custom': true,
     'autoCloseOn': 'click',
     'dy': -316,
     'content': '<div class="content build-content">' +
      '<div class="pop-img"><img src="http://pde56fqkk.bkt.clouddn.com/1544760152593.jpg"/><p class="pop-name build-pop-name" id="viewDetial"><span class="text-ellipsis" title="浦软大厦">浦软大厦</span><a>详情<i class="el-icon-arrow-right"></i></a></p></div>' +
      '<div class="pop-txt"><ul><li>入驻企业:<span>12 家</span> </li><li>登记人员:<span>1000 人</span> </li><li>今日访客:<span>100 人</span> </li><li>登记车辆:<span>500 辆</span> </li><li>实时人数:<span>0 人</span> </li><li>监控点位:<span>0 个</span> </li><li>人脸门禁:<span>0 个</span> </li><li>消防设施:<span>0 个</span></li></ul></div>' +
      '</div>'
    }
    var infoWindow = new maptalks.ui.InfoWindow(options)
    infoWindow.addTo(that.map).show(lonlat)
   }
  } else {
   // 当射线离开的时候变为原来的颜色
   if (INTERSECTED) {
    // INTERSECTED.material.color.set(INTERSECTED.currentHex);
    if (INTERSECTED.material.length === undefined) {
     INTERSECTED.material.color.setHex(INTERSECTED.currentHex)
    } else {
     for (var i = 0; i < INTERSECTED.material.length; i++) {
      INTERSECTED.material[i].color.setHex(INTERSECTED.currentHex)
     }
     // INTERSECTED.scale.set(1,1,1);
    }
   }
   INTERSECTED = null
  }
  threeLayer.renderScene()
 })
 
 function closeBox() {
  var theClose = document.getElementById('close_id')
  var cont = document.getElementById('infow')
  cont.style.display = 'none'
 }
 
 // ///单体化交互结束
 // the ThreeLayer to draw buildings
 // //ThreeLayer初始化
 var threeLayer = new ThreeLayer('t_forbcmp', {
  forceRenderOnMoving: true,
  forceRenderOnRotating: true,
  animation: true
 })
 
 threeLayer.prepareToDraw = function(gl, scene, camera) {
  var me = this
  // var light = new THREE.PointLight(0xffffff);
  // camera.add(light);
  // let axes=new THREE.AxesHelper(200000000);
  // scene.add(axes);
  var light0 = new THREE.DirectionalLight('#ffffff', 0.5)
  light0.position.set(800, 800, 800).normalize()
  light0.castShadow = true
  camera.add(light0)
  // 环境光
  var light01 = new THREE.AmbientLight('#f7fdf9')
  light01.castShadow = true
  scene.add(light01)
  // var light1 = new THREE.DirectionalLight("#ffffff");
  // light1.position.set(-800,-800,800).normalize();
  // light1.castShadow = true;
  // camera.add(light1);
 
  // 测试加载obj和mtl贴图
  // addmtlLoaderTest(13.438186479666001,52.530305072175594);
  // addmtlLoaderTestforMTL(13.436186479666001,52.530305072175594);
  // 相对路径参数,
  var mtlPath = process.env.BASE_URL + 'model/obj/'
  var mtlName = '3d_puruan_new.mtl'
  var objPath = process.env.BASE_URL + 'model/obj/'
  var objName = '3d_puruan3.obj'
  var objlon = 121.60499979860407
  var objlat = 31.20150084741559
  addLoaderForObj(objlon, objlat, mtlPath, mtlName, objPath, objName)
 }
 
 threeLayer.addTo(that.map).hide()
 
 // ////////////////加载模型相关
 // 加载obj+mtl
 function addLoaderForObj(lon, lat, mtlPath, mtlName, objPath, objName) {
  const me = threeLayer
  const scene = me.getScene()
  const scale = -0.0007
  var mtlLoader = new MTLLoader()
  // 加载贴图mtl
  mtlLoader.setPath(mtlPath)
  mtlLoader.load(mtlName, function(materials) {
   materials.preload()
   var objLoader = new OBJLoader()
   objLoader.setMaterials(materials)
   // 加载模型obj Math.PI*3/2
   objLoader.setPath(objPath)
   objLoader.load(objName, function(object) {
    object.traverse(function(child) {
     if (child instanceof THREE.Mesh) {
      child.scale.set(scale, scale, scale)
      child.rotation.set(-Math.PI / 2, Math.PI, 0)
      // 赋予基础材质的颜色,无色(0xFFFFFF)调试色0x0000FF
      for (var i = 0; i < child.material.length; i++) {
       child.material[i].color.setHex(0x0000FF)
      }
     }
    })
 
    var v = threeLayer.coordinateToVector3(new maptalks.Coordinate(lon, lat))
    object.position.set(v.x, v.y, 0)
    scene.add(object)
    mtlLoaded = true
    threeLayer.renderScene()
   })
   // var mm = new THREE.MeshPhongMaterial({color:0xFF0000});
   // objLoader.setMaterials( mm );
   // objLoader.setMaterials(materials);
  })
 }
 var toolbar = new maptalks.control.Toolbar({
  position: { 'right': 40, 'bottom': 40 },
  items: [
   {
    item: '二三维图层切换',
    click: function() {
     if (three_flag === false) {
      that.map.animateTo({
       center: [121.6050804009, 31.2015354151],
       zoom: 18,
       pitch: 45
      }, {
       duration: 2000
      })
      threeLayer.show()
      three_flag = true
     } else {
      that.map.animateTo({
       center: [121.6050804009, 31.2015354151],
       zoom: 18,
       pitch: 0
      }, {
       duration: 2000
      })
      threeLayer.hide()
      three_flag = false
     }
     console.log('obj模型')
    }
   }
  ]
 }).addTo(this.map)
}

上面这段代码需要注意的是模型数据文件的读取路径

// 相对路径参数,
var mtlPath = process.env.BASE_URL + 'model/obj/'
var mtlName = '3d_puruan_new.mtl'
var objPath = process.env.BASE_URL + 'model/obj/'
var objName = '3d_puruan3.obj'

关于process.env.BASE_URL的值可以在vue.config.js里自定义设置(cli3.0)

baseUrl: process.env.NODE_ENV === 'production' ? '/bcmp-web/' : '/',

关于draw3D的代码我没有进行详细的解释,如果需要会出一个详细版的方法使用介绍

补充知识:Vue npm安装Vue常用依赖,axios、element ui、mockjs

添加axios依赖:

npm install axios

添加element-ui:

npm i element-ui -S

添加 mockjs:

npm install mockjs

以上这篇maptalks+three.js+vue webpack实现二维地图上贴三维模型操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 解析url的search方法
Feb 09 Javascript
jQuery.ajax 用户登录验证代码
Oct 29 Javascript
jquery操作angularjs对象
Jun 26 Javascript
深入分析jQuery的ready函数是如何工作的(工作原理)
Dec 17 Javascript
JavaScript对象参数的引用传递
Jan 14 Javascript
JS调用某段SQL语句的方法
Oct 20 Javascript
vue axios用法教程详解
Jul 23 Javascript
微信小程序实现YDUI的ScrollTab组件
Feb 02 Javascript
javascript中的隐式调用
Feb 10 Javascript
element-ui 的el-button组件中添加自定义颜色和图标的实现方法
Oct 26 Javascript
浅谈JavaScript中this的指向更改
Jul 28 Javascript
JavaScript高级程序设计之基本引用类型
Nov 17 Javascript
React实现阿里云OSS上传文件的示例
Aug 10 #Javascript
vue+elementUI(el-upload)图片压缩,默认同比例压缩操作
Aug 10 #Javascript
使用vue引入maptalks地图及聚合效果的实现
Aug 10 #Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
Aug 10 #Javascript
解决vue+webpack项目接口跨域出现的问题
Aug 10 #Javascript
vue 导航锚点_点击平滑滚动,导航栏对应变化详解
Aug 10 #Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
Aug 10 #Javascript
You might like
mysql+php分页类(已测)
2008/03/31 PHP
MYSQL 小技巧 -- LAST_INSERT_ID
2009/11/24 PHP
JS+PHP实现用户输入数字后显示最大的值及所在位置
2017/06/19 PHP
解决PhpStorm64不能启动的问题
2020/06/20 PHP
JavaScript 使用技巧精萃(.net html
2009/04/25 Javascript
几个javascript操作word的参考代码
2009/10/26 Javascript
javascript 文章截取部分无损html显示实现代码
2010/05/04 Javascript
jquery导航制件jquery鼠标经过变色效果示例
2013/12/05 Javascript
Js实现双击鼠标自动滚动屏幕的示例代码
2013/12/14 Javascript
js 弹出虚拟键盘修改密码的简单实例
2016/10/10 Javascript
canvas 画布在主流浏览器中的尺寸限制详细介绍
2016/12/15 Javascript
详解Vue.js分发之作用域槽
2017/06/13 Javascript
JavaScript队列函数和异步执行详解
2017/06/19 Javascript
vue init webpack 建vue项目报错的解决方法
2018/09/29 Javascript
微信小程序实现form表单本地储存数据
2019/06/27 Javascript
layui表单提交到后台自动封装到实体类的方法
2019/09/12 Javascript
vue 导航内容设置选中状态样式的例子
2019/11/01 Javascript
如何利用node转发请求详解
2020/09/17 Javascript
[02:40]DOTA2英雄基础教程 先知
2013/11/29 DOTA
Python去除列表中重复元素的方法
2015/03/20 Python
用python处理图片之打开\显示\保存图像的方法
2018/05/04 Python
浅析Python 读取图像文件的性能对比
2019/03/07 Python
Python实现迪杰斯特拉算法并生成最短路径的示例代码
2020/12/01 Python
8款使用 CSS3 实现超炫的 Loading(加载)的动画效果
2015/03/17 HTML / CSS
CSS3过渡transition效果实例介绍
2016/05/03 HTML / CSS
中国第一家杂志折扣订阅网:杂志铺
2016/08/30 全球购物
香港士多网上超级市场:Ztore
2021/01/09 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
一篇.NET面试题
2014/09/29 面试题
SOA面试题:如何在SOA中实现松耦合
2013/07/21 面试题
小学英语教学反思案例
2014/02/04 职场文书
淘宝活动策划方案
2014/02/06 职场文书
医院保洁服务方案
2014/06/11 职场文书
个人四风问题对照检查材料
2014/09/26 职场文书
大学生党员自我剖析材料
2014/10/06 职场文书
2014年志愿者工作总结
2014/11/20 职场文书