高德地图中加载three.js(vue中)(封装

这几天公司有一个要结合高德地图的智慧园区的项目(大致就是在3d地图中加载自己的three.js模型)

1.首先要引入高德地图

 官方文档给出来的引用方法

<template>
  <div id="container"></div>
</template>

<script>
import AMapLoader from "@amap/amap-jsapi-loader";
export default {
  data() {
    return {
      map: null,
    };
  },
  mounted() {
    //DOM初始化完成进行地图初始化
    this.initMap();
  },
  methods: {
    initMap() {
      AMapLoader.load({
        key: "", // 申请好的Web端开发者Key,首次调用 load 时必填
        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: [""], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      })
        .then((AMap) => {
          this.map = new AMap.Map("container", {
            //设置地图容器id
            viewMode: "3D", //是否为3D地图模式
            zoom: 5, //初始化地图级别
            center: [105.602725, 37.076636], //初始化地图中心点位置
          });
        })
        .catch((e) => {
          console.log(e);
        });
    },
  },
};
</script>

<style  scoped>
#container {
  padding: 0px;
  margin: 0px;
  width: 100%;
  height: 800px;
}
</style>

  因为新的key中增加了秘钥(不加载的话,我们的自定义地图无法加载)

created() {
    window._AMapSecurityConfig = {
      securityJsCode:"",//初始化时加载秘钥
    };
  },

2.接下来就是加载three.js了(这就是封装完成的组件)

<template>
  <!-- 高德地图加载器 -->
  <div class="geomap" ref="geomap" id="container"></div>
</template>

<script>
import * as THREE from "three"; //三维
import AMapLoader from "@amap/amap-jsapi-loader"; //高德地图

export default {
  name: "geomap", //高德地图加载器
  props: {
    // 传入要获取的地图信息
    AMapinfo: {
      type: [Object],
      default: () => {
        return {
          version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
          plugins: [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
          amap: {
            rotateEnable: false, //控制地图是否可以旋转
            pitchEnable: false, //控制地图是否可以倾斜
            pitch: 65, //初始化角度
            viewMode: "3D", //是否为3D地图模式
            zoom: 20, //初始化地图级别
            center: [121.187344, 31.46736], //初始化地图中心点位置
            mapStyle: "amap://styles/id", //初始化地图样式
          },
        };
      },
    },
    //  传入模型函数
    initLoader: {
      type: [Function],
    },
    // 传入光源数组
    lightlist: {
      type: [Array],
      default: () => {
        return [
          {
            type: "AmbientLight", //光的类型
            color: 0xffffff, //光的颜色
            intensity: 1, //光照强度
            posiy: [0, 0, 0], //光照位置
          },
        ];
      },
    },
  },
  data() {
    return {
      map: null, //地图对象
      scene: null, //场景对象Scene
      camera: null, //相机对象
      render: null, //渲染器对象
      isclick: null, //判断鼠标状态
      customCoords: null, //初始化数据转换工具
      security: "", // 初始化时加载秘钥
      key: "", // 申请好的Web端开发者Key,首次调用 load 时必填
      gllayer: null, //three数据
      isadd: false, //是否添加
      aminonte: true,
    };
  },
  created() {
    window._AMapSecurityConfig = {
      securityJsCode: this.security,
    };
  },
  mounted() {
    // 初始化地图数据
    this.initMap();
  },
  methods: {
    // 添加全局方法
    addmeth() {
      // 设置在什么缩放比例的时候隐藏
      this.map.on("zoomend", () => {
        if (this.map.getZoom() < 16.9) {
          this.map.remove(this.gllayer);
          this.isadd = true;
        } else {
          if (this.isadd) {
            this.map.add(this.gllayer);
            this.isadd = false;
          }
        }
      });
      // 监听窗口尺寸变化
      window.addEventListener("resize", this.changeSize, false);
      // 监听鼠标按下
      window.addEventListener("mousedown", this.mouseDown, false);
      //  监听鼠标移动
      window.addEventListener("mousemove", this.mouseMove, false);
      // 监听鼠标弹起
      window.addEventListener("mouseup", this.mouseUp, false);
    },
    // 添加3d
    addthree() {
      // 初始化数据转换工具
      this.customCoords = this.map.customCoords;
      // 经纬度数据转换
      this.customCoords.lngLatsToCoords([this.AMapinfo.amap.center]);
      // 引入three图层
      this.gllayer = new AMap.GLCustomLayer({
        // 图层的层级c
        zIndex: 2000,
        // 初始化的操作,创建图层过程中执行一次。
        init: (gl) => {
          this.render = new THREE.WebGLRenderer({
            context: gl, // 地图的 gl 上下文
            alpha: true,
          });
          //  初始化场景对象
          this.initScene();
          // 初始化模型
          this.initLoader();
          // 初始化光源
          this.initLight();
          // 初始化相机
          this.initCamera();
          // 自动清空画布这里必须设置为 false,否则地图底图将无法显示
          // 这里我们的地图模式是 3D,所以创建一个透视相机,
          // 相机的参数初始化可以随意设置,因为在 render 函数中,每一帧都需要同步相机参数,
          //因此这里变得不那么重要。
          // 如果你需要 2D 地图(viewMode: '2D'),那么你需要创建一个正交相机
          // 环境光照和平行光
          this.render.autoClear = false;
        },
        render: () => {
          this.renderer();
        },
      });
      // 把three图层引入地图
      this.map.add(this.gllayer);
      // 渲染图层
      this.animate();
      // 设置动画
      this.tweenUpdate();
    },
    // 监听鼠标按下
    mouseDown(event) {
      this.isclick = {
        clientX: event.clientX,
        clientY: event.clientY,
      };
    },
    // 监听鼠标移动
    mouseMove(event) {
      this.aminonte = false;
      if (!this.isclick) {
        if (this.$refs.geomap) {
          var list = this.countmouse(event);
          if (list.length > 0) {
            // 传出鼠标移动事件
            this.$emit("change", "move", list);
          }
        }
      }
    },
    // 监听鼠标弹起
    mouseUp(event) {
      // 如果相等说明是点击事件
      if (
        (this.isclick.clientX === event.clientX) &
        (this.isclick.clientY === event.clientY)
      ) {
        // 传出点击事件
        this.isclick = null;
        if (this.$refs.geomap) {
          var list = this.countmouse(event);
          if (list.length > 0) {
            this.$emit("change", "click", list);
          }
        }
      } else {
        this.isclick = null;
      }
    },
    // 判断当前点击的事件
    countmouse(event) {
      let raycaster = new THREE.Raycaster();
      let mouse = new THREE.Vector2();
      //将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标
      var dom = this.$refs.geomap.getBoundingClientRect();
      if (
        event.clientX >= dom.left &&
        event.clientY >= dom.top &&
        event.clientX <= dom.left + this.$refs.geomap.offsetWidth &&
        event.clientY <= dom.top + this.$refs.geomap.offsetHeight
      ) {
        mouse.x = (event.clientX / this.$refs.geomap.offsetWidth) * 2 - 1;
        mouse.y = -(event.clientY / this.$refs.geomap.offsetHeight) * 2 + 1;
        // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
        raycaster.setFromCamera(mouse, this.camera);
        // 获取raycaster直线和所有模型相交的数组集合
        var list = raycaster.intersectObjects(this.scene.children, true);
        if (list.length > 0) {
          return list;
        } else {
          return [];
        }
      } else {
        return [];
      }
    },
    // 监听尺寸变化
    changeSize() {
      //窗口宽高比
      var k = this.$refs.geomap.offsetWidth / this.$refs.geomap.offsetHeight;     
      this.camera.aspect = k;
      this.camera.updateProjectionMatrix();
    },
    // 初始化地图数据
    initMap() {
      AMapLoader.load({
        key: this.key,
        version: this.AMapinfo.version,
        plugins: this.AMapinfo.plugins,
      })
        .then((AMap) => {
          // 初始化地图
          this.map = new AMap.Map("container", this.AMapinfo.amap);
          // 监听事件
          this.addmeth();
          // 添加动画
          this.addthree();
        })
        .catch((e) => {
          this.$message.error(e);
        });
    },
    // 初始化场景对象
    initScene() {
      // 初始化场景
      this.scene = new THREE.Scene();
      // 旋转场景
      this.scene.rotation.x = (Math.PI / 180) * 90;
      this.scene.rotation.y = (Math.PI / 180) * -58;
      this.scene.scale.set(1.18, 1.18, 1.18);
      // 创建三维坐标系
      var axesHelper = new THREE.AxesHelper(100);
      this.scene.add(axesHelper);
    },
    // 初始化光源
    initLight() {
      // 遍历添加光源
      this.lightlist.forEach((item) => {
        var light = new THREE[item.type](item.color, item.intensity);
        light.position.set(item.posiy[0], item.posiy[1], item.posiy[2]); //点光源位置
        if (item.type === "DirectionalLight") {
        }
        this.scene.add(light);
      });
    },
    // 初始化相机
    initCamera() {
      this.camera = new THREE.PerspectiveCamera(
        60,
        this.$refs.geomap.offsetWidth / this.$refs.geomap.offsetHeight,
        100,
        1 << 30
      );
    },
    // 渲染器对象
    renderer() {
      // 这里必须执行!!重新设置 three 的 gl 上下文状态。
      this.render.state.reset();
      var { near, far, fov, up, lookAt, position } =
        this.customCoords.getCameraParams();
      // 2D 地图下使用的正交相机

      // 这里的顺序不能颠倒,否则可能会出现绘制卡顿的效果。
      this.camera.near = near;
      this.camera.far = far;
      this.camera.fov = fov;
      this.camera.position.set(...position);
      this.camera.up.set(...up);
      this.camera.lookAt(...lookAt);
      this.camera.updateProjectionMatrix();

      // 2D 地图使用的正交相机参数赋值
      //   this.camera.top = top;
      //   this.camera.bottom = bottom;
      //   this.camera.left = left;
      //   this.camera.right = right;
      //   this.camera.position.set(...position);
      //   this.camera.updateProjectionMatrix();
      this.render.render(this.scene, this.camera);
    },
    // 动画
    animate() {
      // 渲染时刷新地图
      this.map.render();
      //   添加了一个旋转地图的动画
      if (this.aminonte) {
        var totation = this.map.getRotation();
        // -360 - 360 范围
        // 在-180的时候重置为180 (aminonte是停止一下动画的
        if (totation > -180) {
          this.map.setRotation((totation - 0.2) % 360, true);
        } else if (totation <= -180) {
          this.aminonte = false;
          this.map.setRotation(180, true);
          this.aminonte = true;
        }
      }
      // 自动刷新
      requestAnimationFrame(this.animate);
    },
    // 设置动画
    tweenUpdate() {
      requestAnimationFrame(this.tweenUpdate);
      this.$tweener.update();
    },
    // 运动动画
    tweenobj(object, y) {
      this.$tween.fade(
        object.position,
        {
          x: object.position.x,
          y: object.position.y + y,
          z: object.position.z,
        },
        1000,
        0,
        this.$tweener.Easing.Cubic.InOut
      );
    },
  },
};
</script>

<style lang="less" scoped>
// 高德地图加载器
.geomap {
  width: 100%;
  height: 100%;
  color: transparent;
}
</style>

  这里也是使用tween.js进行一些动画,只按照这篇文章的话可能缺少一些依赖

3.使用方法

  使用的方法和我的另一篇文章一样,链接放下面了

  vue中使用three.js加载各种模型文件(obj,mtl,fbx..)(封装

  你可能缺少的依赖

//three依赖
npm i three 或者 yarn add three
 
//tween.js依赖
npm i @tweenjs/tween.js 或者 yarn add @tweenjs/tween.js 
 
//obj,mtl 文件加载依赖
npm i three-obj-mtl-loader 或者 yarn add three-obj-mtl-loader 
 
//高德地图
npm i @amap/amap-jsapi-loader 或者 yarn add @amap/amap-jsapi-loader

   就是这样,下班!!!

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值