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 相关文章推荐
控制打印时页眉角的代码
Feb 08 Javascript
js 学习笔记(三)
Dec 29 Javascript
jQuery基础知识filter()和find()实例说明
Jul 06 Javascript
javascript中负数算术右移、逻辑右移的奥秘探索
Oct 17 Javascript
table行随鼠标移动变色示例
May 07 Javascript
JQuery操作元素的css样式
Mar 09 Javascript
JS Array创建及concat()split()slice()的使用方法
Jun 03 Javascript
JS实现新建文件夹功能
Jun 17 Javascript
荐书|您有一份JavaScript书单待签收
Jul 21 Javascript
微信小程序实现蒙版弹窗效果
Nov 01 Javascript
create-react-app使用antd按需加载的样式无效问题的解决
Feb 26 Javascript
js实现漂亮的星空背景
Nov 01 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 at(@)符号的用法简介
2009/07/11 PHP
PHP中对用户身份认证实现两种方法
2011/06/04 PHP
PHP数字字符串左侧补0、字符串填充和自动补齐的几种方法
2014/05/10 PHP
PHP程序员必须清楚的问题汇总
2014/12/18 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
2016/01/22 PHP
PHP快速排序quicksort实例详解
2016/09/28 PHP
PHP实现的DES加密解密封装类完整实例
2017/04/29 PHP
详解PHP处理字符串类似indexof的方法函数
2017/06/11 PHP
php操作redis数据库常见方法实例总结
2020/02/20 PHP
javascript入门·对象属性方法大总结
2007/10/01 Javascript
jquery的index方法实现tab效果
2011/02/16 Javascript
jQuery实现页面滚动时层智能浮动定位实例探讨
2013/03/29 Javascript
ie浏览器使用js导出网页到excel并打印
2014/03/11 Javascript
jQuery实现简单网页遮罩层/弹出层效果兼容IE6、IE7
2014/06/16 Javascript
JS实现进入页面时渐变背景色的方法
2015/02/25 Javascript
一个简单的JavaScript Map实例(分享)
2016/08/03 Javascript
微信小程序页面间值传递的两种方法
2018/11/26 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
2020/04/10 Javascript
vue 动态生成拓扑图的示例
2021/01/03 Vue.js
Pycharm学习教程(3) 代码运行调试
2017/05/03 Python
Python使用pickle模块存储数据报错解决示例代码
2018/01/26 Python
解决Django的request.POST获取不到内容的问题
2018/05/28 Python
基于python历史天气采集的分析
2019/02/14 Python
对Python3 * 和 ** 运算符详解
2019/02/16 Python
解决django 新增加用户信息出现错误的问题
2019/07/28 Python
python内打印变量之%和f的实例
2020/02/19 Python
Python3中的f-Strings增强版字符串格式化方法
2020/03/04 Python
Python之变量类型和if判断方式
2020/05/05 Python
使用CSS3实现SVG路径描边动画效果入门教程
2019/10/21 HTML / CSS
HTML5之SVG 2D入门10—滤镜的定义及使用
2013/01/30 HTML / CSS
LN-CC英国:伦敦时尚生活的缩影
2019/09/01 全球购物
Marlies Dekkers内衣荷兰官方网店:荷兰奢侈内衣品牌
2020/03/27 全球购物
酒店营销策划方案
2014/02/07 职场文书
环保公益广告语
2014/03/13 职场文书
应届生求职信
2014/05/31 职场文书
项目合作意向书模板
2014/07/29 职场文书