
前言Cesium 里面有两套绘图 APIEntity高层和Primitive底层。✅ Entity数据驱动写法简单、自带拾取、支持 hover、适合业务可视化点位、围栏、轨迹本文重点❌ Primitive性能更强适合大批量几何、自定义着色器上手复杂业务开发中绝大多数场景优先使用viewer.entities.add()一行代码添加图形支持直接viewer.flyTo定位到实体非常适合大屏、监控、水利、国土类 WebGIS 项目。环境Vue3 Vite Cesium 1.114 script setup组合式 API一、环境搭建ViteVue3 集成 Cesium1. 安装依赖npm install cesium npm install vite-plugin-cesium -D2. vite.config.js 配置import { defineConfig } from vite import vue from vitejs/plugin-vue import cesium from vite-plugin-cesium export default defineConfig({ plugins: [vue(), cesium()] })vite-plugin-cesium 自动处理 Cesium 静态资源、Worker、Assets不用手动拷贝静态文件踩坑最少稀土掘金3. 组件基础容器template div classcesium-container refcesiumRef/div /template style scoped .cesium-container { width: 100%; height: 80vh; } /style二、完整组件代码Entity 绘制各类图形template div classcesium-wrap div classbtn-group button clickaddPoint添加点位/button button clickaddPolyline添加线轨迹/button button clickaddPolygon添加面电子围栏/button button clickaddCircle添加圆形/button button clickaddExtrudedPolygon拉伸立体面/button button clickaddLabel添加文字标签/button button clickclearAllEntity清空所有实体/button /div div classcesium-container refcesiumRef/div /div /template script setup import { ref, onMounted, onUnmounted } from vue import * as Cesium from cesium import cesium/Build/Cesium/Widgets/widgets.css const cesiumRef ref(null) let viewer null // 初始化地图 function initViewer() { viewer new Cesium.Viewer(cesiumRef.value, { animation: false, timeline: false, baseLayerPicker: false, geocoder: false, homeButton: false, fullscreenButton: false, navigationHelpButton: false }) // 定位到国内 viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(108.95, 34.27, 80000) }) } // 1. 添加点实体 function addPoint() { const pointEntity viewer.entities.add({ name: 监测点位, position: Cesium.Cartesian3.fromDegrees(108.95, 34.27, 500), point: { pixelSize: 12, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2, disableDepthTestDistance: Number.POSITIVE_INFINITY // 永远不被遮挡 } }) viewer.flyTo(pointEntity) } // 2. 添加线polyline 轨迹线支持贴地 function addPolyline() { const positions Cesium.Cartesian3.fromDegreesArray([ 108.90, 34.27, 108.93, 34.30, 108.98, 34.28, 109.01, 34.31 ]) const lineEntity viewer.entities.add({ name: 巡检轨迹, polyline: { positions: positions, width: 4, material: Cesium.Color.CYAN, clampToGround: true // 贴地形 } }) viewer.flyTo(lineEntity) } // 3. 多边形面电子围栏 function addPolygon() { const polygonHierarchy Cesium.Cartesian3.fromDegreesArray([ 108.92, 34.25, 108.96, 34.25, 108.96, 34.29, 108.92, 34.29 ]) const polygonEntity viewer.entities.add({ name: 区域围栏, polygon: { hierarchy: polygonHierarchy, material: Cesium.Color.BLUE.withAlpha(0.3), outline: true, outlineColor: Cesium.Color.BLUE, outlineWidth: 2 } }) viewer.flyTo(polygonEntity) } // 4. 圆形/椭圆 function addCircle() { const circleEntity viewer.entities.add({ name: 圆形缓冲区, position: Cesium.Cartesian3.fromDegrees(108.95, 34.27, 100), ellipse: { semiMajorAxis: 1500, // 长半轴 m semiMinorAxis: 1500, // 短半轴 m 相等就是正圆 material: Cesium.Color.ORANGE.withAlpha(0.35), outline: true, outlineColor: Cesium.Color.ORANGE } }) viewer.flyTo(circleEntity) } // 5. 拉伸立体面extrudedHeight 高度拉伸 function addExtrudedPolygon() { const hierarchy Cesium.Cartesian3.fromDegreesArray([ 108.94, 34.26, 108.97, 34.26, 108.97, 34.28, 108.94, 34.28 ]) const extrudeEntity viewer.entities.add({ name: 立体建筑块, polygon: { hierarchy: hierarchy, height: 0, extrudedHeight: 600, // 拉伸高度 material: Cesium.Color.GREEN.withAlpha(0.4), outline: true, outlineColor: Cesium.Color.GREEN } }) viewer.flyTo(extrudeEntity) } // 6. 文字标签 label function addLabel() { const labelEntity viewer.entities.add({ name: 文字标注, position: Cesium.Cartesian3.fromDegrees(108.95, 34.27, 800), label: { text: 西安点位, font: 16px sans-serif, fillColor: Cesium.Color.WHITE, outlineColor: Cesium.Color.BLACK, outlineWidth: 2, pixelOffset: new Cesium.Cartesian2(0, -20), disableDepthTestDistance: Number.POSITIVE_INFINITY } }) viewer.flyTo(labelEntity) } // 清空所有实体 function clearAllEntity() { viewer.entities.removeAll() } onMounted(() { initViewer() }) onUnmounted(() { viewer?.destroy() }) /script style scoped .cesium-wrap { width: 100%; height: 100vh; } .btn-group { padding: 10px; background: #fff; z-index: 9; position: relative; } button { margin: 0 4px; padding: 6px 10px; } .cesium-container { width: 100%; height: calc(100vh - 50px); } /style三、Entity 核心知识点讲解1. 坐标转换重点Cesium 内部渲染用Cartesian3笛卡尔空间坐标我们开发习惯传经纬度工具函数// 经纬度 [lon, lat, height] → Cartesian3 Cesium.Cartesian3.fromDegrees(lon, lat, height) // 经纬度数组批量转适合线和面 Cesium.Cartesian3.fromDegreesArray([lon1,lat1,lon2,lat2...])2. 常用图形字段对照表表格属性 key图形类型核心参数point点pixelSize、color、outlinepolyline线positions、width、clampToGround 贴地polygon面hierarchy、extrudedHeight 拉伸高度ellipse圆 / 椭圆semiMajorAxis、semiMinorAxislabel文字text、font、pixelOffsetbillboard图片图标image、scale3. 贴地属性clampToGroundpolylineclampToGround:true线条贴地形起伏polygon 贴地如果需要贴地形面优先使用GroundPolygon普通 polygon 不贴地4. 实体的拾取、点击Entity 自带 id点击拾取非常方便viewer.screenSpaceEventHandler.setInputAction((e){ const pick viewer.scene.pick(e.position) if(Cesium.defined(pick) Cesium.defined(pick.id)){ console.log(点击实体, pick.id.name) } }, Cesium.ScreenSpaceEventType.LEFT_CLICK)5. 实体单独删除不是清空全部const entity viewer.entities.add({...}) viewer.entities.remove(entity)四、常见踩坑记录重点线 polyline 宽度大于 1px 不生效WebGL 底层限制原生 polyline 最大宽度 1px粗线要用PolylineOutlineMaterialProperty图形被地形遮挡点 /label 添加disableDepthTestDistance: Number.POSITIVE_INFINITY贴地面 polygon 拉伸失效贴地图形不能设置 extrudedHeight二者互斥页面销毁白屏、内存泄漏onUnmounted 必须执行viewer.destroy()flyTo 动画viewer.flyTo(entity)自动计算包围盒比 camera.flyTo 写坐标省心很多Cesium五、Entity vs Primitive 怎么选少量图形、需要点击拾取、业务标注、围栏点位Entity上千、上万海量几何追求渲染性能Primitive GeometryInstance六、拓展方向动态绘制鼠标点击绘制多边形、绘制线自定义材质流动线、渐变面、闪烁点位EntityCollection 分组管理分层显隐结合 Cesium 的 DataSource 加载 GeoJSON 生成 Entity
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。