前端地图可视化的新宠儿:Cesium 地图封装实践

0 阅读3分钟

Cesium地图二次封装与实战应用(附完整源码)

本文将带你如何用 JavaScript 对 Cesium 地图进行二次封装,并在 Vue(包含vue2、vue3) 项目中实现丰富的地图交互功能。文末附完整源码,适合前端地图开发者参考和实践。


一、为什么要封装 Cesium 地图?

Cesium 是业界领先的 WebGL 三维地球引擎,功能强大但 API 较为底层。实际项目中,我们常常需要:

  • 统一管理地图实例
  • 简化点、线、面、围栏、3D Tiles 等常用操作
  • 支持自定义交互、测量、标注、弹窗等业务需求

因此,进行一层面向业务的封装,可以极大提升开发效率和代码可维护性。


二、CesiumMap.js 封装核心代码

我们将 Cesium 的常用操作封装成一个类,支持点、线、面、圆、围栏、3D Tiles、热力图、测量、截图等功能。

文件结构:

src/
  utils/
    CesiumMap.js   // Cesium地图封装
  components/
    CesiumMapDemo.vue  // Vue组件实战

1. CesiumMap.js 封装类(核心片段)

// src/utils/CesiumMap.js
import * as Cesium from 'cesium';

Cesium.Ion.defaultAccessToken = '你的CesiumToken';

export default class CesiumMap {
  constructor(containerId, options = {}) {
    this.viewer = new Cesium.Viewer(containerId, {
      animation: false,
      timeline: false,
      baseLayerPicker: false,
      // ... 其他参数
      ...options
    });
  }

  // 添加点
  addEntity(entityOptions) {
    return this.viewer.entities.add(entityOptions);
  }

  // 移除实体
  removeEntity(entity) {
    this.viewer.entities.remove(entity);
  }

  // 相机飞行
  flyTo(target, options = {}) {
    // 支持实体、坐标、数组等多种形式
    // ... 见完整代码
  }

  // 添加marker
  addMarker({ lon, lat, image, width = 32, heightPx = 32, name = '', description = '' }) {
    return this.viewer.entities.add({
      name,
      position: Cesium.Cartesian3.fromDegrees(lon, lat),
      billboard: { image, width, height: heightPx },
      description,
    });
  }

  // 添加折线
  addPolyline({ positions, color = Cesium.Color.BLUE, width = 3, name = '', description = '' }) {
    return this.viewer.entities.add({
      name,
      polyline: {
        positions: positions.map(p => Cesium.Cartesian3.fromDegrees(...p)),
        width,
        material: color,
      },
      description,
    });
  }

  // 添加圆
  addCircle({ lon, lat, radius, color = Cesium.Color.GREEN.withAlpha(0.5), outlineColor = Cesium.Color.GREEN, outlineWidth = 2, name = '', description = '' }) {
    return this.viewer.entities.add({
      name,
      position: Cesium.Cartesian3.fromDegrees(lon, lat),
      ellipse: {
        semiMajorAxis: radius,
        semiMinorAxis: radius,
        material: color,
        outline: true,
        outlineColor,
        outlineWidth,
      },
      description,
    });
  }

  // ... 还有多边形、围栏、3D Tiles、热力图、测量等方法
  // 见文末完整代码
}

完整 CesiumMap.js 源码见项目仓库或文末下载方式。


三、Vue3 组件实战:CesiumMapDemo.vue

我们将 CesiumMap 封装类应用到 Vue3 组件中,实现丰富的地图交互。

1. 组件结构

<template>
  <div class="cesium-map-demo">
    <div ref="mapContainer" class="map-container"></div>
    <div class="toolbar">
      <button @click="addPoint">添加点</button>
      <button @click="addPolyline">画线</button>
      <button @click="addCircle">画圆</button>
      <button @click="addPolygon">画多边形</button>
      <!-- ... 其他按钮 ... -->
    </div>
    <div v-if="measureResult" class="measure-result">{{ measureResult }}</div>
    <!-- 属性弹窗 -->
    <div v-if="popupVisible" class="popup" :style="{ left: popupScreen.x + 'px', top: popupScreen.y + 'px' }" v-html="popupContent"></div>
  </div>
</template>

2. 组件核心逻辑

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import CesiumMap from '../utils/CesiumMap';

const mapContainer = ref(null);
let cesiumMap = null;
let pointEntity = null;
let polylineEntity = null;
let circleEntity = null;
let polygonEntity = null;

onMounted(() => {
  cesiumMap = new CesiumMap(mapContainer.value);
  // 注册实体点击事件,显示弹窗
  cesiumMap.onEntityClick(({ entity, screenPosition }) => {
    // ... 弹窗逻辑
  });
});

onBeforeUnmount(() => {
  cesiumMap && cesiumMap.destroy();
});

// 添加点
function addPoint() {
  if (pointEntity) return;
  pointEntity = cesiumMap.addEntity({
    position: CesiumMap.Cartesian3.fromDegrees(116.3913, 39.9075, 100),
    point: { pixelSize: 10, color: CesiumMap.Color.RED },
    description: '北京',
  });
}

// 添加折线
function addPolyline() {
  if (polylineEntity) return;
  polylineEntity = cesiumMap.addPolyline({
    positions: [
      [116.3913, 39.9075],
      [116.3974, 39.9087],
      [116.4053, 39.9200],
    ],
    color: CesiumMap.Color.BLUE,
    width: 4,
    name: '示例线',
    description: '北京示例线',
  });
}

// ... 还有画圆、画多边形、交互绘制、测量、围栏、弧形、标记点等丰富功能
</script>

完整 CesiumMapDemo.vue 源码见文末。


四、主要功能亮点与效果说明

  • 支持点、线、面、圆、围栏、3D Tiles、热力图等一键添加
  • 支持鼠标交互绘制线、面、圆、围栏、弧形
  • 支持距离、面积测量
  • 支持属性弹窗、标记点、围栏管理等
  • 支持相机飞行、截图、事件注册等高级功能
  • 兼容性检测,适配不同 Cesium 版本

效果演示:

  • 具体效果可以到文本末进行下载查看

image.png

五、总结与参考

通过对 Cesium 地图的二次封装,我们可以极大提升三维地图开发效率,并实现高度可复用、可维护的业务组件。

本方案支持点、线、面、圆、围栏、3D Tiles、热力图、测量、截图、弹窗等常用功能,适合大部分前端三维可视化项目。 可以直接将CesiumMap.js拿到你的项目中直接使用,最好使用和uncleTom一样的版本 uncleTom用的版本是 cesium: 1.130.1-splats.0

参考链接:


demo源码地址: uncleTom/Cesium-utils

如有任何问题,欢迎评论区留言交流!希望这篇文章对你能用帮助,如果喜欢给uncleTom点个关注哟,我以后也会多多分享更多前端内容