欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-01 17:45:01
我们不是走在坑里就是走在前往坑的路上_(:зゝ∠)_最终效果如图:(地图上添加一个“三维地图”的toolbar按钮,点击后在二维地图上贴上建好的三维模型点击显示弹框)以下都在已经引入并且初始化mapt...

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

最终效果如图:(地图上添加一个“三维地图”的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实现二维地图上贴三维模型操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。