GIS-3D:添加模型与气泡

前言

在上一章节中,我们已经绘制出实际的GIS地图,实际的需求中,我们可能需要在地图的某些位置添加一些标注,比如建筑、车辆,点击标注弹出详细的信息框。
本章节中,介绍如何在GIS地图中添加标注,并自定义气泡。

一、添加模型

GIS地图中,使用模型来设置标注。

为什么使用模型,而不是图片?GIS是一个3D的场景,使用模型更有立体感,使用图片的话,不能与3D的场景进行很好的结合,导致显示有瑕疵。
通过(https://www.aigei.com/),可下载免费的模型。

  // 创建一个模型对象
  const position = Cesium.Cartesian3.fromDegrees(108.919_093, 34.136_449, 0.07);
  const heading = Cesium.Math.toRadians(0);
  const pitch = 0;
  const roll = 0;
  const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
  const orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    hpr,
  );
  const entity = viewer.value.entities.add({
    name: 'sceneCar',
    id: 'car',
    position,
    orientation,
    model: {
      uri: `${import.meta.env.VITE_BASE}/assets/model/bmw.glb`,
      scale: 2,
      maximumScale: 400,
    },
  });

参数中的uri是模型的绝对地址,要保证打包部署后,也能通过该地址找到对应的模型,否则地图上无法展示对象的模型。

二、自定义气泡

Cesium中未提供相应的API来自定义气泡,所以我们只能自己进行开发。

  • 创建气泡元素
   // carPopStyle使用ts进行控制
    <div class="ol-popup" :style="carPopStyle" v-if="showCarPop">
      <CarPopup @close="handleCloseCarPopup" />
    </div>
  • 设置气泡样式

.ol-popup {
  position: absolute;
  width: 350px;
  height: 390px;
  background-color: white;
  border: 1px solid #eee;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgb(0 0 0 / 15%);
}

.ol-popup::after,
.ol-popup::before {
  position: absolute;
  top: 100%;
  width: 0;
  height: 0;
  pointer-events: none;
  content: ' ';
  border: solid transparent;
}

.ol-popup::after {
  left: 170px;
  margin-left: -10px;
  border-width: 10px;
  border-top-color: white;
}

.ol-popup::before {
  left: 170px;
  margin-left: -11px;
  border-width: 11px;
  border-top-color: #ccc;
}
  • 增加点击事件,弹出气泡
  // 点击的标注对象
  const trackPop = ref<any>(null);
  const carPopStyle = ref({
    top: '0px',
    left: '0px',
  });

  const handler = new Cesium.ScreenSpaceEventHandler(viewer.value.canvas);
  // 监听鼠标点击事件
  handler.setInputAction((click: any) => {
    // 使用pick函数获取点击位置的实际位置
    const pick = viewer.value.scene.pick(click.position);
    // 根据id来判断点击的标注
    if (pick && pick.id._id === 'car') {
      trackPop.value = pick.id.position._value;
      // 将GIS地图的坐标,转化为屏幕上的点的坐标
      const winpos = viewer.value.scene.cartesianToCanvasCoordinates(
        pick.id.position._value,
      );
      // 计算气泡的坐标
      carPopStyle.value = {
        left: `${winpos.x - 170}px`,
        top: `${winpos.y - 390 - 20}px`,
      };
      showCarPop.value = true;
    } else {
      trackPop.value = undefined;
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  • 监听GIS地图的渲染,并实时更新气泡的坐标

通过鼠标缩放、移动地图时,标注坐标对应的屏幕的坐标也会发生改变,所以需要同步更新气泡的屏幕坐标

  // 监听地图的渲染
  viewer.value.scene.postRender.addEventListener(() => {
    if (trackPop.value && showCarPop.value) {
      const winpos = viewer.value.scene.cartesianToCanvasCoordinates(
        trackPop.value,
      );
      carPopStyle.value = {
        left: `${winpos.x - 170}px`,
        top: `${winpos.y - 390 - 20}px`,
      };
    }
  });

三、源代码

demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容