效果图:2D
效果图:3D
maptalks地图官网案例
https://maptalks.org/examples/cn/map/load/#map_load
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、安装vue-video-player视频包
npm install vue-video-player --save
5、安装maptalks 地图包
npm install maptalks --save
<template>
<div id="map" class="container"></div>
</template>
<script>
import * as maptalks from "maptalks";
import videojs from "video.js";
import "video.js/dist/video-js.css";
import "vue-video-player/src/custom-theme.css";
import "videojs-flash";
import * as THREE from "three";
import { ThreeLayer } from "maptalks.three";
import { MTLLoader, OBJLoader } from "three-obj-mtl-loader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
export default {
name: "BaseMap",
data() {
return {
videoPlayer: null,
map: null,
layer_monitor: null,
layer_fire: null,
monitor: [],
fire: [],
three_flag: false,
};
},
mounted() {
const that = this;
// 初始化maptalks地图
this.map = new maptalks.Map("map", {
center: [116.267462, 40.046213],
zoom: 18,
baseLayer: new maptalks.TileLayer("base", {
urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>',
}),
// spatialReference: {
// projection: "EPSG:4326",
// },
// baseLayer: new maptalks.WMSTileLayer("wms", {
// tileSystem: [1, -1, -180, 90],
// urlTemplate: "https://ows.terrestris.de/osm/service",
// crs: "EPSG:4326",
// layers: "OSM-WMS",
// styles: "",
// version: "1.3.0",
// format: "image/png",
// transparent: true,
// uppercase: true,
// }),
// attribution: {
// // 左下角info
// content: "© ows.terrestris.de",
// },
});
// 声明放置监控设备的图层
this.layer_monitor = new maptalks.VectorLayer("monitor").addTo(this.map);
// 声明放置消防设施的图层
this.layer_fire = new maptalks.VectorLayer("fire").addTo(this.map);
// 监听地图点击事件
this.map.on("click", function (e) {
if (that.videoPlayer) {
that.videoPlayer.dispose();
that.videoPlayer = null;
}
});
// 监控设备上图
this.getMarks();
// 加载模型
this.draw3D();
},
methods: {
// 渲染三维
draw3D() {
const that = this;
// 三维地图
// 加载gltf
// the ThreeLayer to draw buildings
var threeLayergltf = new ThreeLayer("t", {
forceRenderOnMoving: true,
forceRenderOnRotating: true,
animation: true,
});
threeLayergltf.prepareToDraw = function (gl, scene, camera) {
// 环境光
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, -10, 10).normalize();
scene.add(light);
camera.add(new THREE.PointLight("#fff", 4));
// 模型路径 放到public下
var modelName = "scene.gltf";
var modelPath = "/gltf/";
// 地图坐标
var modellon = 116.267962;
var modellat = 40.046893;
addGltf(modelName, modelPath, modellon, modellat);
};
// 添加到地图
threeLayergltf.addTo(this.map).hide();
// gltf模型渲染
function addGltf(modelName, modelPath, modellon, modellat) {
// 声明参数
const me = threeLayergltf;
const scene = me.getScene();
const scale = 0.002;
// 加载GLTFLoader模型
var gltfloader = new GLTFLoader();
gltfloader.setPath(modelPath);
gltfloader.load(modelName, (gltf) => {
// 获取模型参数
var model = gltf.scene.children[0];
// 控制模型大小
model.scale.set(scale, scale, scale);
// 模型在maptalks的位置
var v = threeLayergltf.coordinateToVector3(
new maptalks.Coordinate(modellon, modellat)
);
model.position.set(v.x, v.y, 0);
// 模型在地图上角度
model.rotation.set(Math.PI, Math.PI, 0);
// 放进模型
scene.add(model);
// 渲染
threeLayergltf.renderScene();
});
}
// 加载obj+mtl
// ThreeLayer初始化
var threeLayer = new ThreeLayer("t_forbcmp", {
forceRenderOnMoving: true,
forceRenderOnRotating: true,
animation: true,
});
threeLayer.prepareToDraw = function (gl, scene, camera) {
var me = this;
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 mtlPath = "/model/";
var mtlName = "Shirley.mtl";
var objPath = "/model/";
var objName = "Shirley.obj";
//116.267462, 40.046213
var objlon = 116.266462;
var objlat = 40.046893;
addLoaderForObj(objlon, objlat, mtlPath, mtlName, objPath, objName);
};
threeLayer.addTo(that.map).hide();
// 加载模型相关
function addLoaderForObj(lon, lat, mtlPath, mtlName, objPath, objName) {
const me = threeLayer;
const scene = me.getScene();
const scale = 1;
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) {
// 控制模型大小
var v = threeLayer.coordinateToVector3(new maptalks.Coordinate(lon, lat));
object.scale.set(scale, scale, scale);
// 模型角度
object.rotation.set(Math.PI / 2, Math.PI / 7, 0);
// 模型位置
object.position.set(v.x, v.y, 0);
// 渲染
scene.add(object);
threeLayer.renderScene();
});
});
}
// 二三维图层切换
var toolbar = new maptalks.control.Toolbar({
position: { right: 40, bottom: 40 },
items: [
{
item: "二三维图层切换",
click: function () {
if (that.three_flag === false) {
that.map.animateTo(
{
center: [116.267462, 40.046213],
zoom: 18,
pitch: 45,
},
{
duration: 2000,
}
);
threeLayer.show();
threeLayergltf.show();
// 标注点显示隐藏
that.layer_monitor.hide();
that.layer_fire.hide();
that.three_flag = true;
} else {
that.map.animateTo(
{
center: [116.267462, 40.046213],
zoom: 18,
pitch: 0,
},
{
duration: 2000,
}
);
threeLayer.hide();
threeLayergltf.hide();
// 标注点显示隐藏
that.layer_monitor.show();
that.layer_fire.show();
that.three_flag = false;
}
console.log("obj模型");
},
},
],
}).addTo(this.map);
},
// 模拟数据
getMarks() {
const that = this;
const res = [
// {
// id: 11,
// type: "monitor",
// name: "奥克斯广场5楼H座",
// position: [116.267162, 40.046413],
// },
{
id: 12,
type: "fire",
name: "奥克斯广场4楼H座",
position: [116.267462, 40.046213],
},
{
id: 14,
type: "fire",
name: "奥克斯广场4楼H座",
position: [116.267162, 40.046413],
},
{
id: 13,
type: "monitor",
name: "奥克斯广场3楼H座",
position: [116.267762, 40.046613],
},
];
const monitor = [];
const fire = [];
res.forEach((item, index) => {
if (item.type === "monitor") {
monitor.push(item);
}
if (item.type === "fire") {
fire.push(item);
}
});
that.monitor = monitor;
that.fire = fire;
that.markerInMap();
},
// 地图标注点
markerInMap() {
const that = this;
for (var m = 0; m < that.monitor.length; m++) {
// lon and lat in here
var markerm = new maptalks.Marker(that.monitor[m].position, {
// 图形样式
symbol: {
markerFile: require("../assets/logo.png"),
markerWidth: 28,
markerHeight: 36,
markerDx: 0,
markerDy: 0,
markerOpacity: 1,
},
}).addTo(that.layer_monitor);
markerm
.setInfoWindow({
autoPan: true,
width: 330,
minHeight: 330,
dy: 4,
custom: false, // 只使用定制自定义true
autoOpenOn: "click", // set to null if not to open when clicking on marker
autoCloseOn: "click",
// 支持自定义html内容
content:
'<div class="content equip-content">' +
'<div class="pop-video"><video id="video_' +
that.monitor[m].id +
'" class="video-js vjs-default-skin vjs-big-play-centered" controls fluid="true" width="485" height="275">' +
' <source src="rtmp://212.64.34.125:10935/hls/stream_27" type="rtmp/flv">' +
"</video></div>" +
'<div class="pop-bottom">' +
that.monitor[m].name +
'<a id="moreMonitor" style="cursor:pointer;" data-id="' +
that.monitor[m].id +
'">查看更多<i class="el-icon-arrow-right"></i></a></div>' +
"</div>",
})
.on("mousedown", onClick);
function onClick(e) {
setTimeout(function () {
const moreMonitor = document.getElementById("moreMonitor");
moreMonitor.onclick = function () {
that.$router.push({
path: "/video/realMonitor",
query: { id: moreMonitor.dataset.id },
});
};
that.videoPlayer = videojs(
document.getElementById("video_" + moreMonitor.dataset.id),
{},
function () {
this.play();
}
);
}, 1000);
}
}
for (var w = 0; w < that.fire.length; w++) {
var videos = require("../../public/4.mp4");
// 图形标志
var marker1 = new maptalks.Marker(that.fire[w].position, {
symbol: {
markerFile: require("../assets/logo.png"),
markerWidth: 28,
markerHeight: 40,
markerDx: 0,
markerDy: 0,
markerOpacity: 1,
},
}).addTo(that.layer_fire);
marker1.setInfoWindow({
autoPan: true,
width: 330,
minHeight: 330,
dy: 4,
custom: false, // 只使用定制自定义true
autoOpenOn: "click", // set to null if not to open when clicking on marker
autoCloseOn: "click",
// 支持自定义html内容
content:
"<div><video src=" +
videos +
' controls autoplay="autoplay"' +
' loop="-1" muted="muted" type="video/mp4" width="300" height="200"></video>' +
"</div>",
});
}
},
},
};
</script>
<style lang="less">
.container {
width: 100%;
height: 100%;
}
</style>
这里会出现three的错误
需要在node_module > three-obj-mtl-loader > index.js中找到第543行并注释掉。在 545行重新定义loader
// var loader = THREE.Loader.Handlers.get( url );
var loader = manager.getHandler(url);
模型放在public里
参考原文链接:https://blog.csdn.net/liona_koukou/article/details/85231410