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:
          '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <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: "&copy 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

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用three.js加载gltf模型时,可能会遇到模型自带的材质加载不出来的问题,这可能是因为模型的材质格式不被three.js所支持。解决这个问题的方法是将模型的材质转化为可以被three.js所识别的材质格式。你可以使用GLTFLoader加载模型后,通过遍历模型的材质数组,将每个材质转化为对应的three.js材质类型,例如THREE.MeshBasicMaterial、THREE.MeshLambertMaterial、THREE.MeshPhongMaterial等。具体的实现可以参考以下代码示例: ```javascript var loader = new THREE.GLTFLoader(); loader.load( 'model.gltf', function ( gltf ) { gltf.scene.traverse( function ( child ) { if ( child.isMesh ) { for ( var i = 0; i < child.material.length; i ++ ) { var material = child.material[ i ]; if ( material.isGLTFSpecularGlossinessMaterial ) { material = THREE.MeshStandardMaterial().copy( material ); } else if ( material.isGLTFMaterial ) { material = THREE.MeshStandardMaterial().copy( material ); material.map = null; material.lightMap = null; material.aoMap = null; material.emissiveMap = null; material.bumpMap = null; material.normalMap = null; material.displacementMap = null; material.roughnessMap = null; material.metalnessMap = null; } material.needsUpdate = true; child.material[ i ] = material; } } } ); scene.add( gltf.scene ); }, undefined, function ( e ) { console.error( e ); } ); ``` 在这个示例,我们通过遍历模型的材质数组,将每个材质转化为THREE.MeshStandardMaterial类型,这是three.js支持的一种材质类型。如果你的模型不支持这种材质类型,你可以根据你的模型选择其他的材质类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值