您好,登錄后才能下訂單哦!
這篇文章主要介紹maptalks+three.js+vue webpack實(shí)現(xiàn)二維地圖上貼三維模型的方法是什么,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
我們不是走在坑里就是走在前往坑的路上_(:зゝ∠)_
最終效果如圖:(地圖上添加一個(gè)“三維地圖”的toolbar按鈕,點(diǎn)擊后在二維地圖上貼上建好的三維模型點(diǎn)擊顯示彈框)
以下都在已經(jīng)引入并且初始化maptalks地圖的基礎(chǔ)上,如何引入使用maptalks可以查看以下文章
https://www.jb51.net/article/192983.htm
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下(放在這里是因?yàn)榇虬笞x取路徑問(wèn)題,目前發(fā)現(xiàn)放在這里才能在打包后正確讀?。?/p>
5、Vue頁(yè)面代碼
引入包
import * as THREE from 'three' import * as maptalks from 'maptalks' import { ThreeLayer } from 'maptalks.three' import { MTLLoader, OBJLoader } from 'three-obj-mtl-loader'
初始化的地圖對(duì)象是
this.map
下面是渲染三維模型的方法
// 渲染三維 draw3D() { const that = this // 三維地圖 var three_flag = false // ///單體化交互開(kāi)始 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) // 這里我們操作第一個(gè)相交的物體 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 // 設(shè)置相交的第一個(gè)物體的顏色 // INTERSECTED.currentHex = INTERSECTED.material[0].color.getHex(); INTERSECTED.currentHex = 16777215 // 將該物體設(shè)為隨機(jī)的其他顏色 // 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>入駐企業(yè):<span>12 家</span> </li><li>登記人員:<span>1000 人</span> </li><li>今日訪(fǎng)客:<span>100 人</span> </li><li>登記車(chē)輛:<span>500 輛</span> </li><li>實(shí)時(shí)人數(shù):<span>0 人</span> </li><li>監(jiān)控點(diǎn)位:<span>0 個(gè)</span> </li><li>人臉門(mén)禁:<span>0 個(gè)</span> </li><li>消防設(shè)施:<span>0 個(gè)</span></li></ul></div>' + '</div>' } var infoWindow = new maptalks.ui.InfoWindow(options) infoWindow.addTo(that.map).show(lonlat) } } else { // 當(dāng)射線(xiàn)離開(kāi)的時(shí)候變?yōu)樵瓉?lái)的顏色 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' } // ///單體化交互結(jié)束 // 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) // 環(huán)境光 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); // 測(cè)試加載obj和mtl貼圖 // addmtlLoaderTest(13.438186479666001,52.530305072175594); // addmtlLoaderTestforMTL(13.436186479666001,52.530305072175594); // 相對(duì)路徑參數(shù), 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() // ////////////////加載模型相關(guān) // 加載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) // 賦予基礎(chǔ)材質(zhì)的顏色,無(wú)色(0xFFFFFF)調(diào)試色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) }
上面這段代碼需要注意的是模型數(shù)據(jù)文件的讀取路徑
// 相對(duì)路徑參數(shù), 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'
關(guān)于process.env.BASE_URL的值可以在vue.config.js里自定義設(shè)置(cli3.0)
baseUrl: process.env.NODE_ENV === 'production' ? '/bcmp-web/' : '/',
關(guān)于draw3D的代碼我沒(méi)有進(jìn)行詳細(xì)的解釋?zhuān)绻枰獣?huì)出一個(gè)詳細(xì)版的方法使用介紹
補(bǔ)充知識(shí):Vue npm安裝Vue常用依賴(lài),axios、element ui、mockjs
添加axios依賴(lài):
npm install axios
添加element-ui:
npm i element-ui -S
添加 mockjs:
npm install mockjs
以上是maptalks+three.js+vue webpack實(shí)現(xiàn)二維地圖上貼三維模型的方法是什么的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。