Skip to content

渲染事件

  1. 监听相机移动开始,获取相机位置
  2. 限制高频事件的处理频率(性能优化),实现事件节流(每 1000ms 最多触发一次)
  3. 自定义事件总线
展开代码
vue
<template>
  <div ref="cesiumContainer" class="container"></div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import * as Cesium from "cesium";
const cesiumContainer = ref(null);
let viewer = null;

// 天地图TOKEN
const token = "05be06461004055923091de7f3e51aa6";

onMounted(() => {
  // 初始化Viewer
  viewer = new Cesium.Viewer(cesiumContainer.value, {
    geocoder: false, // 关闭地理编码搜索
    homeButton: false, // 关闭主页按钮
    sceneModePicker: false, // 关闭场景模式选择器
    baseLayerPicker: false, // 关闭底图选择器
    navigationHelpButton: false, // 关闭导航帮助
    animation: false, // 关闭动画控件
    timeline: false, // 关闭时间轴
    fullscreenButton: false, // 关闭全屏按钮
    baseLayer: false, // 关闭默认地图
  });
  // 清空logo
  viewer.cesiumWidget.creditContainer.style.display = "none";
  initMap();

  // 1. 监听相机移动开始
  viewer.camera.moveStart.addEventListener(() => {
    console.log("相机开始移动");
  });

  // 监听相机移动结束、获取相机位置
  viewer.camera.moveEnd.addEventListener(() => {
    const positionCartographic = viewer.camera.positionCartographic;
    let cameraPosition = {};
    cameraPosition.y = Number(
      Cesium.Math.toDegrees(positionCartographic.latitude).toFixed(6)
    );
    cameraPosition.x = Number(
      Cesium.Math.toDegrees(positionCartographic.longitude).toFixed(6)
    );
    cameraPosition.z = Number(positionCartographic.height.toFixed(1));
    cameraPosition.heading = Number(
      Cesium.Math.toDegrees(viewer.camera.heading || -90).toFixed(1)
    );
    cameraPosition.pitch = Number(
      Cesium.Math.toDegrees(viewer.camera.pitch || 0).toFixed(1)
    );
    cameraPosition.roll = Number(
      Cesium.Math.toDegrees(viewer.camera.roll || 0).toFixed(1)
    );
    console.log("相机位置", cameraPosition);
  });

  // 监听相机位置或方向发生变化
  viewer.camera.changed.addEventListener(() => {
    console.log("相机位置或方向发生变化");
  });

  // 2. 限制高频事件的处理频率(性能优化)
  // 实现事件节流(每1000ms最多触发一次)
  function throttle(fn, interval = 1000) {
    let lastTime = 0;
    return (...args) => {
      const now = Date.now();
      if (now - lastTime >= interval) {
        fn.apply(this, args);
        lastTime = now;
      }
    };
  }

  // 应用于高频事件
  const throttledUpdate = throttle((scene, time) => {
    // 执行需要节流的逻辑,如更新UI位置
  }, 1000);

  viewer.scene.postUpdate.addEventListener(throttledUpdate);

  // 3. 自定义事件总线
  const eventBus = {
    events: {},
    emit(event, data) {
      if (this.events[event]) {
        this.events[event].forEach((fn) => fn(data));
      }
    },
    on(event, callback) {
      if (!this.events[event]) this.events[event] = [];
      this.events[event].push(callback);
    },
  };
  const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  // 在实体点击时触发自定义事件
  handler.setInputAction((click) => {
    const picked = viewer.scene.pick(click.position);
    if (picked && picked.id) {
      eventBus.emit("entity-clicked", picked);
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  // 监听自定义事件
  eventBus.on("entity-clicked", (picked) => {
    console.log("实体被点击:", picked);
  });
});

// 加载天地图
const initMap = () => {
  // 以下为天地图及天地图标注加载
  const tiandituProvider = new Cesium.WebMapTileServiceImageryProvider({
    url:
      "http://{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" +
      token,
    layer: "img",
    style: "default",
    format: "tiles",
    tileMatrixSetID: "w",
    subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"], // 子域名
    maximumLevel: 18,
    credit: new Cesium.Credit("天地图影像"),
  });
  // 天地图影像添加到viewer实例的影像图层集合中
  viewer.imageryLayers.addImageryProvider(tiandituProvider);
};
</script>
<style scoped>
.container {
  width: 100vw;
  height: 100vh;
}
</style>