Cesium(三)添加标记点、绘制线并清除,添加wms影像底图 前面写了Cesium的基本初始化视角切换和测量工具的使用。这一篇我们要实现在地球上添加标记点和标记线的功能并且提供了添加wms影像底图的方法。一、初始化地球1.环境变量配置Cesium的部分功能使用需要 Ion Token 前往Cesium 官网申请并在.env.development文件中配置 VITE_CESIUM_ION_TOKEN你的Cesium Ion Token2. 封装组件 CesiumEntity.tsx引入Cesium核心库与样式创建Viewer实例import { useEffect, useRef, useState } from react; import * as Cesium from cesium; import { Viewer, Cartesian3, Color, Ion, Entity } from cesium; // 导入 Cesium 样式文件必须引入否则控件样式异常 import cesium/Build/Cesium/Widgets/widgets.css; import ./index.scss; const {VITE_CESIUM_ION_TOKEN} import.meta.env // 使用你的Token令牌 Cesium.Ion.defaultAccessToken VITE_CESIUM_ION_TOKEN const CesiumEntity: React.FC{} () { const center [116.41, 39.92, 100000] as [number, number, number]; //北京市 const containerRef useRefHTMLDivElement(null); const viewerRef useRefCesium.Viewer | null(null); const [isLoading, setIsLoading] useState(true); const [error, setError] useStatestring | null(null); useEffect(() { if (!containerRef.current) return; try { setIsLoading(true); // 创建 Viewer const viewer new Cesium.Viewer(containerRef.current, { // 控件配置 显示/隐藏 shouldAnimate: false, animation: false, //动画 baseLayerPicker: true, //图层选择器 fullscreenButton: true, //全屏按钮 vrButton: false, //VR效果 homeButton: true, //返回默认视角 infoBox: true, sceneModePicker: true, //场景模式切换2D/3D selectionIndicator: false, timeline: false, //时间轴 navigationHelpButton: true, //帮助说明按钮 navigationInstructionsInitiallyVisible: false, //帮助说明是否默认打开 // 性能优化 targetFrameRate: 60, useBrowserRecommendedResolution: false, }); viewerRef.current viewer; // 视角定位到中国-北京区域 if (viewerRef.current) { viewerRef.current.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(center[0], center[1], center[2]), duration: 2 // 动画时长秒默认3 }); } setIsLoading(false); } catch (err) { console.error(Failed to initialize Cesium:, err); setError(err instanceof Error ? err.message : Failed to initialize Cesium); setIsLoading(false); } // 清理函数 return () { if (viewerRef.current) { moveHandlerRef.current?.destroy(); viewerRef.current.destroy(); viewerRef.current null; } }; }, []); // 只在组件挂载时初始化一次 return ( div classNamecesium-earth div ref{containerRef} classNamecesium-viewer-container / {isLoading ( div classNameloading-overlay div classNameloading-spinner / p加载地球中.../p /div )} {error ( div classNameerror-overlay p错误: {error}/p button onClick{() window.location.reload()}重试/button /div )} /div ) }; export default CesiumEntity;二、添加标记点和线1. html结构定义div classNametoolbar button onClick{addPointDrawer}添加标记点/button button onClick{addLineDrawer}添加标记线/button button onClick{clearEntityAll}全部清空/button /div2. 定义绘制方法我们先定义个模拟数据const mockData [ { id: 1, name: 天安门, lon: 116.392, lat: 39.899 }, { id: 2, name: 前门, lon: 116.395, lat: 39.879 }, { id: 3, name: 鸟巢, lon: 116.391, lat: 39.99 }, { id: 4, name: 圆明园, lon: 116.298, lat: 40.006 }, { id: 5, name: 长城, lon: 116.03, lat: 40.36 }, ]1标记点这里添加的标记点用到了图片React语法引入图片import markerImg from ../assets/marker.png;定义绘制点的方法// 添加标记点 const addPointDrawer () { if (!viewerRef.current) return; mockData.forEach(item { if (!item.lon || !item.lat) return; // 移除已存在的实体 const existingEntity viewerRef.current?.entities.getById(point_ item.id); if (existingEntity) { viewerRef.current?.entities.remove(existingEntity); } const position Cartesian3.fromDegrees(item.lon, item.lat, 0); // 创建实体 viewerRef.current!.entities.add({ id: point_ item.id, //实体id position, // 使用billboard添加图片 billboard: { image: markerImg, // 图片URL verticalOrigin: VerticalOrigin.BOTTOM, // 垂直对齐 horizontalOrigin: HorizontalOrigin.CENTER, // 水平对齐 }, // 添加标签 label: { text: ${item.name}, font: 16px Microsoft YaHei, Arial, sans-serif, fillColor: Color.WHITE, pixelOffset: new Cartesian3(0, -60), verticalOrigin: VerticalOrigin.BOTTOM, horizontalOrigin: HorizontalOrigin.CENTER, showBackground: true, backgroundColor: Color.fromCssColorString(radial-gradient( 124.72% 50% at 50% 50%, rgba(35,50,58,0.88) 0%, rgba(35,50,58,0.88) 61.5%, rgba(0,42,66,0) 100%);), backgroundPadding: new Cesium.Cartesian2(10, 5), }, properties: { ...item } }); }) }2标记线我们就还用模拟的数据作为线的连接点。要注意线的经纬度是放在一个数组中的格式[经度1, 纬度1, 经度2, 纬度2, ...]// 添加线 const addLineDrawer () { if (!viewerRef.current) return; // 定义线的经纬度坐标点 [经度1, 纬度1, 经度2, 纬度2, ...] const degrees [mockData[0].lon, mockData[0].lat, mockData[2].lon, mockData[2].lat, mockData[3].lon, mockData[3].lat, mockData[4].lon, mockData[4].lat]; // 转换为 Cesium 需要的笛卡尔坐标 const positions Cesium.Cartesian3.fromDegreesArray(degrees); // 添加一条带箭头的红色线 viewerRef.current!.entities.add({ polyline: { positions, width: 8, material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED), //可以定制线的样式如颜色、发光、轮廓或箭头等 }, }); }3清除方法清除某个entity实体// 移除已存在的实体 const existingEntity viewerRef.current?.entities.getById(point_2); if (existingEntity) { viewerRef.current?.entities.remove(existingEntity); }清除单个实体的方法是 remove()像这样就移除了 [前门] 这个标记点清空全部entity// 清掉全部entity const clearEntityAll () { viewerRef.current?.entities.removeAll(); }清除全部实体的方法是 removeAll()。这个方法会把地图上的所有entity标记都清楚掉三、添加wms影像底图有的项目中不想用Cesium默认的底图想使用自己提供的wms底图。方法如下写在Viewer创建之后const wmsImageryProvider new Cesium.WebMapServiceImageryProvider({ url: http://111/geoserver/daxing_img/wms, //后端给的url layers: daxing, parameters: { service: WMS, version: 1.1.0, request: GetMap, format: image/png, //一定是png格式jpg不支持透明背景 transparent: true, srs: EPSG:4326 // 注意: WMS 1.3.0使用crs而不是srs }, tilingScheme: new Cesium.GeographicTilingScheme(), // 地理分块方案 }) const wmsLayer new Cesium.ImageryLayer(wmsImageryProvider, { show: true, // 是否显示 alpha: 1.0, // 透明度0-1 brightness: 1.0, // 亮度 contrast: 1.0, // 对比度 hue: 0.0, // 色调 saturation: 1.0, // 饱和度 gamma: 1.0, // 伽马校正 minimumTerrainLevel: 4, // 最小地形级别 maximumTerrainLevel: 18 // 最大地形级别 } ); viewer.imageryLayers.add(wmsLayer) //添加底图图层四、代码仓库项目的完整代码已上传至Giteecesium-react-demo可直接克隆运行