vue使用maptalks地图+three加载video视频obj+mtl和gltf模型
Posted 瞌睡虫、、
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue使用maptalks地图+three加载video视频obj+mtl和gltf模型相关的知识,希望对你有一定的参考价值。
效果图: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使用 Vue-cli 和 Three.js 加载 STL 文件
【中文标题】使用 Vue-cli 和 Three.js 加载 STL 文件【英文标题】:Loading STL files with Vue-cli and Three.js
【发布时间】:2021-05-26 15:29:06
【问题描述】:
我目前遇到的问题是我无法将 STL 文件加载到通过 vue-cli 创建的 three.js 场景中。
使用 vue-cli 'vue init webpack ProjectName', 'cd ProjectName', 'npm install three --save' 设置项目,并用此代码替换 'HelloWorld' 组件。
stl 文件和这个 vue 组件在同一个文件夹中。
<template>
<div id="container"></div>
</template>
<script>
import * as THREE from 'three'
import STLLoader from 'three/examples/jsm/loaders/STLLoader.js';
export default
name: 'ThreeTest',
data()
return
cube: null,
renderer: null,
scene: null,
camera: null
,
methods:
init: function()
this.scene = new THREE.Scene()
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
this.renderer = new THREE.WebGLRenderer()
this.renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(this.renderer.domElement)
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial( color: 0x00ff00 )
this.cube = new THREE.Mesh(geometry, material)
var loader = new STLLoader();
loader.load( 'test.stl', function ( geometry )
var material = new THREE.MeshPhongMaterial(
ambient: 0xff5533,
color: 0xff5533,
specular: 0x111111,
shininess: 200
);
mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0, 100, 0);
this.scene.add(mesh)
, undefined, function ( error ) console.error( error ); );
// this.scene.add(this.cube)
this.camera.position.z = 5
const animate = function()
,
animate: function()
requestAnimationFrame(this.animate)
this.cube.rotation.x += 0.01
this.cube.rotation.y += 0.01
this.renderer.render(this.scene, this.camera)
,
mounted()
this.init()
this.animate()
</script>
我不知道为什么我有这个错误的黑屏:
RangeError: Invalid typed array length: 5202511335
at new Float32Array (<anonymous>)
at parseBinary (STLLoader.js?e2c6:199)
at STLLoader.parse (STLLoader.js?e2c6:396)
at Object.eval [as onLoad] (STLLoader.js?e2c6:87)
at XMLHttpRequest.eval
有人可以帮我吗?
谢谢! :)
问候
【问题讨论】:
您能否通过浏览器的开发控制台从后端实际加载一个 STL 文件(而不是 HTML)?有时,用户将资产放入错误的目录,从而导致服务不正确。
你能解释一下我如何验证我实际加载了一个 stl 文件吗?我是网络开发新手,所以我没有所有技巧:/。我在 init 函数的开头放置了一个运行良好的 console.log("Model") (它不在这篇文章中,因为我是在之后做的)。
【参考方案1】:
回答
我安装了最新版本的 vue-cli,它有一个“公共”文件夹。我还安装了hujiulong的“vue-3d-model”,现在它工作正常! :D
我不知道是什么问题,也许 Vue 在没有公用文件夹的情况下具有受限权限?
【讨论】:
以上是关于vue使用maptalks地图+three加载video视频obj+mtl和gltf模型的主要内容,如果未能解决你的问题,请参考以下文章
THREE.JS学习使用THREEJS加载GeoJSON地图数据
基于Echarts+百度地图+Three.js的数据可视化系统