《cesium项目实战》如何解决海量Label文本堆叠问题

177 阅读1分钟

项目中可能会有大量的label文本文字显示在地图上,如果不做任何处理,文本文字会都堆叠在一起,用户体验也特别差,解决这一问题的思路是:将label文本文字的经纬度转成屏幕坐标,检测文本文字之间的屏幕坐标差值,以第一个label文件文字的位置为起始点,逐一比较后面的label文本文字,如果差值小于设定的某一个值,则将后面的label文本文字设置为隐藏,直到距离大于设定的某一个值,记录此时的index,然后再以该label文本文字为起点,递归处理后面的数据。

function labelToggleByCameraChange(map, labels, minZoom = 13.5) {
  console.log("map, labels", map, labels);
  let viewer = map.map;
  let scene = viewer.scene;
  map.labelToggleByCameraChangeFlag = false;
  const labelToggleByCameraChangeEvent = () => {
    if (map.labelToggleByCameraChangeFlag) {
      return;
    }
    map.labelToggleByCameraChangeFlag = true;
    let zoom = map.getZoom();
    console.log("zoom", zoom);
    if (zoom > minZoom) {
      for (let i = 1; i < labels.length; i++) {
        labels[i].show();
      }
      map.labelToggleByCameraChangeFlag = false;
    } else {
      // 视高 km
      let alt = (viewer.camera.positionCartographic.height / 1000).toFixed(2);
      // 方位角
      let heading = Cesium.Math.toDegrees(viewer.camera.heading).toFixed(2);
      // 俯仰角
      let pitch = Cesium.Math.toDegrees(viewer.camera.pitch).toFixed(2);
      // 翻滚角
      let roll = Cesium.Math.toDegrees(viewer.camera.roll).toFixed(2);
      // 级别
      let level = 0;
      let tileRender = viewer.scene._globe._surface._tilesToRender;
      if (tileRender && tileRender.length > 0) {
        level = viewer.scene._globe._surface._tilesToRender[0]._level;
      }
      let str = `级数:${level} 视高:${alt}km  方位角:${heading}° 俯仰角:${pitch}° 翻滚角:${roll}°`;
      // console.log(str);

      let showIndex = 0;
      let windowCoord0 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
        scene,
        Cesium.Cartesian3.fromDegrees(...labels[0].getPosition())
      );
      if (!windowCoord0) {
        map.labelToggleByCameraChangeFlag = false;
      } else {
        let temX = windowCoord0.x;
        let temY = windowCoord0.y;

        for (let i = 1; i < labels.length; i++) {
          let position = labels[i].getPosition();
          let windowCoord = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
            scene,
            Cesium.Cartesian3.fromDegrees(...position)
          );
          let text = labels[i].options.text;
          // console.log("windowCoord", windowCoord);
          if (windowCoord) {
            if (
              Math.abs(windowCoord.y - temY) < 50 &&
              Math.abs(windowCoord.x - temX) < text.length * 10
            ) {
              labels[i].hide();
            } else {
              labels[i].show();
              temY = windowCoord.y;
              temX = windowCoord.x;
            }
          }
        }
        map.labelToggleByCameraChangeFlag = false;
      }
    }
  };
  console.log("map.cameraChangedHandler", map.cameraChangedHandler);
  if (map.cameraChangedHandler) {
    map.cameraChangedHandler();
  }
  labelToggleByCameraChangeEvent()
  let cameraChangedHandler = viewer.camera.changed.addEventListener(
    labelToggleByCameraChangeEvent
  );
  map.cameraChangedHandler = cameraChangedHandler;
}