maptalks+three.js+vue webpack实现二维地图上贴三维模型操作

我们不是走在坑里就是走在前往坑的路上_(:зゝ∠)_

最终效果如图:(地图上添加一个“三维地图”的toolbar按钮,点击后在二维地图上贴上建好的三维模型点击显示弹框)

以下都在已经引入并且初始化maptalks地图的基础上,如何引入使用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下(放在这里是因为打包后读取路径问题,目前发现放在这里才能在打包后正确读取)

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实现二维地图上贴三维模型操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

以上是 maptalks+three.js+vue webpack实现二维地图上贴三维模型操作 的全部内容, 来源链接: utcz.com/p/237847.html

回到顶部