当前位置: 移动技术网 > IT编程>开发语言>JavaScript > maptalks+three.js+vue webpack实现二维地图上贴三维模型操作

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

2020年08月11日  | 移动技术网IT编程  | 我要评论

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

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

以下都在已经引入并且初始化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下(放在这里是因为打包后读取路径问题,目前发现放在这里才能在打包后正确读取)

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实现二维地图上贴三维模型操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网