maptalks+three.js+vue webpack實(shí)現(xiàn)二維地圖上貼三維模型操作
我們不是走在坑里就是走在前往坑的路上_(:зゝ∠)_
最終效果如圖:(地圖上添加一個(gè)“三維地圖”的toolbar按鈕,點(diǎn)擊后在二維地圖上貼上建好的三維模型點(diǎn)擊顯示彈框)

以下都在已經(jīng)引入并且初始化maptalks地圖的基礎(chǔ)上,如何引入使用maptalks可以查看以下文章
http://www.dbjr.com.cn/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取路徑問題,目前發(fā)現(xiàn)放在這里才能在打包后正確讀取)

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
// ///單體化交互開始
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>今日訪客:<span>100 人</span> </li><li>登記車輛:<span>500 輛</span> </li><li>實(shí)時(shí)人數(shù):<span>0 人</span> </li><li>監(jiān)控點(diǎn)位:<span>0 個(gè)</span> </li><li>人臉門禁:<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)射線離開的時(shí)候變?yōu)樵瓉淼念伾?
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ì)的顏色,無色(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的代碼我沒有進(jìn)行詳細(xì)的解釋,如果需要會(huì)出一個(gè)詳細(xì)版的方法使用介紹
補(bǔ)充知識(shí):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實(shí)現(xiàn)二維地圖上貼三維模型操作就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue3除了keep-alive還有哪些實(shí)現(xiàn)頁(yè)面緩存詳解
Vue3中的keep-alive組件用于緩存頁(yè)面,以便在切換頁(yè)面時(shí)保留其狀態(tài),下面這篇文章主要給大家介紹了關(guān)于Vue3除了keep-alive還有哪些實(shí)現(xiàn)頁(yè)面緩存的相關(guān)資料,需要的朋友可以參考下2024-04-04
SpringBoot+Vue3實(shí)現(xiàn)上傳文件功能
這篇文章主要介紹了SpringBoot+Vue3實(shí)現(xiàn)上傳文件功能,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
vue中用動(dòng)態(tài)組件實(shí)現(xiàn)選項(xiàng)卡切換效果
本篇文章主要介紹了vue中用動(dòng)態(tài)組件實(shí)現(xiàn)選項(xiàng)卡切換效果,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
詳解vue-cli項(xiàng)目中怎么使用mock數(shù)據(jù)
這篇文章主要介紹了vue-cli項(xiàng)目中怎么使用mock數(shù)據(jù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
vue中js判斷長(zhǎng)時(shí)間不操作界面自動(dòng)退出登錄(推薦)
這篇文章主要介紹了vue中js判斷長(zhǎng)時(shí)間不操作界面自動(dòng)退出登錄,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
vue.js與后臺(tái)數(shù)據(jù)交互的實(shí)例講解
今天小編就為大家分享一篇vue.js與后臺(tái)數(shù)據(jù)交互的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08

