maptalks+three.js+vue webpack项目实现二维地图上贴三维模型
我们不是走在坑里就是走在前往坑的路上_(:зゝ∠)_
最终效果如图:(地图上添加一个“三维地图”的toolbar按钮,点击后在二维地图上贴上建好的三维模型点击显示弹框)
以下都在已经引入并且初始化maptalks地图的基础上,如何引入使用maptalks可以查看博客https://blog.csdn.net/liona_koukou/article/details/84316065
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 INTERSECTEDthis.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) returnconst size = that.map.getSize()const width = size.width; const height = size.heightmouse.x = (e.containerPoint.x / width) * 2 - 1mouse.y = -((e.containerPoint.y) / height) * 2 + 1raycaster.setFromCamera(mouse, camera)raycaster.linePrecision = 3var intersects = raycaster.intersectObjects(scene.children, true)// var intersects = raycaster.intersectObject(points);if (!intersects) returnif (Array.isArray(intersects) && intersects.length === 0) returnconsole.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.coordinateif (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 = truecamera.add(light0)// 环境光var light01 = new THREE.AmbientLight('#f7fdf9')light01.castShadow = truescene.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.60499979860407var objlat = 31.20150084741559addLoaderForObj(objlon, objlat, mtlPath, mtlName, objPath, objName)}threeLayer.addTo(that.map).hide()// 加载模型相关// 加载obj+mtlfunction addLoaderForObj(lon, lat, mtlPath, mtlName, objPath, objName) {const me = threeLayerconst scene = me.getScene()const scale = -0.0007var mtlLoader = new MTLLoader()// 加载贴图mtlmtlLoader.setPath(mtlPath)mtlLoader.load(mtlName, function(materials) {materials.preload()var objLoader = new OBJLoader()objLoader.setMaterials(materials)// 加载模型obj Math.PI*3/2objLoader.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)调试色0x0000FFfor (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 = truethreeLayer.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的代码我没有进行详细的解释,如果需要会出一个详细版的方法使用介绍
maptalks+three.js+vue webpack项目实现二维地图上贴三维模型相关推荐
- 寻路优化(一)——二维地图上A*启发函数的设计探索
工作中需要优化A*算法,研究了一天,最后取得了不错的效果.看网上的朋友还没有相关的研究,特此记录一下.有错误欢迎大家批评指正.如需转载请注明出处,http://www.cnblogs.com/Leon ...
- unity三维地图的经纬度如何在二维地图上表示_安全数据分析:数据点—地图—线性回归...
一次性进群,长期免费索取教程,没有付费教程. 教程列表见微信公众号底部菜单 进微信群回复公众号:微信群:QQ群:460500587 微信公众号:计算机与网络安全 ID:Computer-network ...
- unity三维地图的经纬度如何在二维地图上表示_接入C++版本recastnavigation寻路库到Unity/服务端中...
前言 因为Unity版本的更新迭代,老版本的A*插件在新版本Unity已经无法正常使用,包括一些运行时代码也已经过时,重新接入要花费很多时间,干脆接入一个新的寻路方案吧. 这里选择的是久负盛名的htt ...
- unity三维地图的经纬度如何在二维地图上表示_三维GIS与游戏引擎的跨界融合,打造数字化孪生的平行世界...
▲点击关注,收获更多GIS精彩 游戏地图在游戏中起基础和关键作用,它承载游戏中的各种资源,是游戏系统中非常重要的组成部分(图1),所以游戏通常具有明显的地理意义.因此,虽然三维GIS与游戏引擎是两个不 ...
- 二维地图展示爆管分析
作者:doremi 管线系统管理目前大多数都是使用三维客户端来实现的,爆管分析也是在三维客户端上展示的.但是最近有很多客户的来电询问如何在二维地图上实现管线的一些分析功能.因此,本文将介绍如何在二维地 ...
- 踩坑之旅:springboot+vue+webpack项目实战(一)
2019独角兽企业重金招聘Python工程师标准>>> 网上关于springboot的小项目很多,node.js+vue的项目也很多,但是好像没有两者合一的项目,最近在想实践下将两者 ...
- vue+webpack项目打包后背景图片加载不出来问题解决
vue+webpack项目打包后背景图片加载不出来问题解决 参考文章: (1)vue+webpack项目打包后背景图片加载不出来问题解决 (2)https://www.cnblogs.com/mica ...
- Vue项目生成二维码
场景: [民主测评.闭卷测试] Vue项目生成二维码,使用手机浏览器扫码录入答题 一,创建vue项目,样式布局,接口联调, npm run build 打包成dist 文件,让后台发送到服务器中,页面 ...
- vue 根据链接生成二维码(功能实现)
今天同事问我一个问题,在vue项目中想要根据一个链接显示对应的二维码该怎么实现. 我前一段时间,有用apicloud项目生成二维码的功能,但是vue版本的没有处理过.百度后找到一个可行的方案: 大神实 ...
最新文章
- nginx+lua实现上传文件到OSS
- javascript document对象 第21节
- Android关闭USB的ADB调试和文件传输功能(禁用USB)
- python2中的print语句可以不用小括号。_Python 2与Python 3的区别
- .net MVC(存储过程+SQLHelper)
- 关于Heap Dump
- Hibernate:More than one row with the given identifier was found解决办法
- JavaScript提高:006:ASP.NET使用easyUI TABS标签updatepanel
- .Net 下的Wondows窗体常用项目
- 什么是瑞利分布和准静态平坦衰落信道?
- 数字信号处理教程答案及解析(第五版)
- Cadence PSpice 仿真3: 电容器充放电瞬态仿真图文教程
- 从零开始的运维之路【标题党】
- 手机wap端用户注册表单(html+css)
- php zen kaku代表什么,Convert kana one from another (zen-kaku, han-kaku and more) - PHP 7 中文文档...
- python 修改图片尺寸_用Python更改图片尺寸大小
- Python作图总结——plot,subplots
- (01)ORB-SLAM2源码无死角解析-(58) 闭环线程→计算Sim3: 源码Sim3Solver::iterate()讲解
- [阮一峰]腾讯的历史.转帖
- 128道软件测试面试题,总结目前互联网公司最常问的面试题
热门文章
- fMRI Tutorial:FSL处理功能核磁共振数据
- access与project与python的区别_Access与 Excel区别
- android广告页白屏_微信官方朋友圈广告营销技巧
- 小程序05 canvas绘图并保存到相册
- 在若依项目中添加导入excel功能
- OR(odd ratios)
- 宝塔面板专业版企业版教程 纯手动 带原版脚本 插件免费用
- CDR插件开发之Addon插件005 - Corel.Interop.VGCore.dll库文件简介
- npm 全局安装 yarn、tsc、rimraf 不是内部或外部命令
- 231个web前端的javascript特效分享(仅供本人学习,非教程类型)