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 相关文章推荐
jQuery.ajax 用户登录验证代码
Oct 29 Javascript
JQuery之拖拽插件实现代码
Apr 14 Javascript
Jquery ajax 同步阻塞引起的UI线程阻塞问题
Nov 17 Javascript
CSS或者JS实现鼠标悬停显示另一元素
Jan 22 Javascript
详解javascript传统方法实现异步校验
Jan 22 Javascript
Bootstrap在线电子商务网站实战项目5
Oct 14 Javascript
JQuery.validationEngine表单验证插件(推荐)
Dec 10 Javascript
react-native使用react-navigation进行页面跳转导航的示例
Sep 07 Javascript
Vue仿支付宝支付功能
May 25 Javascript
浅谈Javascript常用正则表达式应用
Mar 08 Javascript
React中Ref 的使用方法详解
Apr 28 Javascript
jQuery实现开关灯效果
Aug 02 jQuery
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
回答PHPCHINA上的几个问题:URL映射
2007/02/14 PHP
php中的观察者模式
2010/03/24 PHP
php pdo oracle中文乱码的快速解决方法
2016/05/16 PHP
Laravel框架中Blade模板的用法示例
2017/08/30 PHP
PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】
2018/06/13 PHP
jQuery窗口、文档、网页各种高度的精确理解
2014/07/02 Javascript
javascript中apply/call和bind的使用
2017/02/15 Javascript
JS实现根据密码长度显示安全条功能
2017/03/08 Javascript
图解Javascript——作用域、作用域链、闭包
2017/03/21 Javascript
jQuery实现checkbox全选功能完整实例
2018/07/12 jQuery
vue2.0 使用element-ui里的upload组件实现图片预览效果方法
2018/09/04 Javascript
Node.JS获取GET,POST数据之queryString模块使用方法详解
2020/02/06 Javascript
[41:08]TNC vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
简单介绍Python中的decode()方法的使用
2015/05/18 Python
Python手机号码归属地查询代码
2016/05/04 Python
Python编程实现的简单神经网络算法示例
2018/01/26 Python
python读取csv文件并把文件放入一个list中的实例讲解
2018/04/27 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
用Python抢火车票的简单小程序实现解析
2019/08/14 Python
py-charm延长试用期限实例
2019/12/22 Python
Python综合应用名片管理系统案例详解
2020/01/03 Python
如何基于python实现不邻接植花
2020/05/01 Python
查看keras的默认backend实现方式
2020/06/19 Python
keras输出预测值和真实值方式
2020/06/27 Python
Trina Turk官网:美国时装和泳装品牌
2018/06/10 全球购物
实习自我鉴定模板
2013/09/28 职场文书
关于旷工的检讨书
2014/02/02 职场文书
员工晚婚的请假条
2014/02/08 职场文书
教师专业自荐书范文
2014/02/10 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
新员工入职欢迎词
2015/01/23 职场文书
2015年会计人员工作总结
2015/05/22 职场文书
党章学习心得体会2016
2016/01/14 职场文书
六年级数学教学反思
2016/02/16 职场文书
Python实现位图分割的效果
2021/11/20 Python
利用Python多线程实现图片下载器
2022/03/25 Python