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格式化数字的函数代码
Nov 30 Javascript
GRID拖拽行的实例代码
Jul 18 Javascript
JS获取单击按钮单元格所在行的信息
Jun 17 Javascript
js代码验证手机号码和电话号码是否合法
Jul 30 Javascript
JS+CSS实现美化的下拉列表框效果
Aug 11 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
Feb 13 Javascript
Vue from-validate 表单验证的示例代码
Sep 26 Javascript
JavaScript反射与依赖注入实例详解
May 29 Javascript
使用electron制作满屏心特效的示例代码
Nov 27 Javascript
微信小程序添加插屏广告并设置显示频率(一天一次)
Dec 06 Javascript
Vue 解决父组件跳转子路由后当前导航active样式消失问题
Jul 21 Javascript
Javascript异步流程控制之串行执行详解
Sep 27 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
一些常用的php函数
2006/12/06 PHP
PHP快速排序quicksort实例详解
2016/09/28 PHP
php实现分页功能的详细实例方法
2019/09/29 PHP
HTML中Select不用Disabled实现ReadOnly的效果
2008/04/07 Javascript
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
js设置function参数默认值(适合没有传参情况)
2014/02/24 Javascript
node.js实现BigPipe详解
2014/12/05 Javascript
javascript引用类型指针的工作方式
2015/04/13 Javascript
动态创建按钮的JavaScript代码
2016/01/29 Javascript
深入浅析JS的数组遍历方法(推荐)
2016/06/15 Javascript
jQuery ajax调用后台aspx后台文件的两种常见方法(不是ashx)
2016/06/28 Javascript
基于angularJS的表单验证指令介绍
2016/10/21 Javascript
详解在Angular项目中添加插件ng-bootstrap
2017/07/04 Javascript
利用js实现前后台传送Json的示例代码
2018/03/29 Javascript
基于Vue自定义指令实现按钮级权限控制思路详解
2018/05/23 Javascript
小程序实现展开/收起的效果示例
2018/09/22 Javascript
javascript创建元素和删除元素实例小结
2019/06/19 Javascript
es6函数之尾递归用法实例分析
2020/04/25 Javascript
Vue父子组件传值的一些坑
2020/09/16 Javascript
Python中__call__用法实例
2014/08/29 Python
django ManyToManyField多对多关系的实例详解
2019/08/09 Python
python线程安全及多进程多线程实现方法详解
2019/09/27 Python
解决windows下python3使用multiprocessing.Pool出现的问题
2020/04/08 Python
Python学习之路之pycharm的第一个项目搭建过程
2020/06/18 Python
python读取图像矩阵文件并转换为向量实例
2020/06/18 Python
Python实现打包成库供别的模块调用
2020/07/13 Python
python中return不返回值的问题解析
2020/07/22 Python
Python连接Impala实现步骤解析
2020/08/04 Python
大学生优秀的自我评价分享
2013/10/22 职场文书
艾滋病宣传活动总结
2014/05/08 职场文书
本科毕业生应聘自荐信范文
2014/06/26 职场文书
代领学位证书毕业证书委托书
2014/09/30 职场文书
2015年世界卫生日活动总结
2015/02/09 职场文书
党员年终个人总结
2015/02/14 职场文书
钱学森电影观后感
2015/06/04 职场文书
公司周年庆寄语
2019/06/21 职场文书