@xingm/vmap-cesium-toolbar 0.0.1-beta.2 → 0.0.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -615
- package/dist/index.js +487 -277
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +18 -18
- package/dist/index.umd.js.map +1 -1
- package/dist/package.json +4 -4
- package/package.json +1 -1
- package/dist/README.md +0 -585
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/libs/CesiumMapHelper.ts","../src/libs/CesiumMapToolbar.ts","../src/libs/CesiumMapLoader.ts","../src/index.ts"],"sourcesContent":["import * as Cesium from \"cesium\";\nimport type { Primitive } from \"cesium\";\nimport type { FrustumOptions } from \"./CesiumMapModel\";\n/**\n * Cesium 绘图辅助工具类\n * 支持绘制点、线、多边形、矩形,并提供编辑和删除功能\n * 适用于 Cesium 1.132.0\n */\nclass DrawHelper {\n private viewer: Cesium.Viewer;\n private scene: Cesium.Scene;\n private entities: Cesium.EntityCollection;\n private frustumPrimitives: Primitive[] = [];\n\n // 绘图状态和数据\n private drawMode: \"line\" | \"polygon\" | \"rectangle\" | null = null;\n private isDrawing: boolean = false;\n private tempPositions: Cesium.Cartesian3[] = [];\n private tempEntities: Cesium.Entity[] = []; // 临时实体,用于绘制过程中\n private finishedEntities: Cesium.Entity[] = []; // 已完成的实体\n\n // 事件处理器\n private screenSpaceEventHandler: Cesium.ScreenSpaceEventHandler | null = null;\n // 回调函数\n private onDrawStartCallback: (() => void) | null = null;\n private onDrawEndCallback: ((entity: Cesium.Entity | null) => void) | null =\n null;\n private onEntityRemovedCallback: ((entity: Cesium.Entity) => void) | null =\n null;\n\n /**\n * 构造函数\n * @param viewer Cesium Viewer 实例\n */\n constructor(viewer: Cesium.Viewer) {\n if (!viewer || !(viewer instanceof Cesium.Viewer)) {\n throw new Error(\"Invalid Cesium Viewer instance provided.\");\n }\n this.viewer = viewer;\n this.scene = viewer.scene;\n this.entities = viewer.entities;\n\n // 确保启用地形深度测试以获得正确的高度\n this.scene.globe.depthTestAgainstTerrain = true;\n }\n\n clearFrustum(): void {\n // 清理视锥体图元\n this.frustumPrimitives.forEach((primitive) => {\n if (primitive && !primitive.isDestroyed()) {\n this.viewer.scene.primitives.remove(primitive);\n }\n });\n this.frustumPrimitives = [];\n \n // 清理视锥体专用的事件处理器\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n // 视锥体功能\n drawFrustum(options: FrustumOptions = {}): void {\n try {\n this.clearFrustum();\n \n // 参数验证\n const fov = Math.max(1, Math.min(179, options.fov || 60)); // 限制FOV范围\n const aspectRatio = Math.max(0.1, options.aspectRatio || 1.0);\n const near = Math.max(0.1, options.near || 1.0);\n const far = Math.max(near + 1, options.far || 1000.0);\n \n const position = options.position || this.viewer.camera.positionWC;\n const orientation =\n options.orientation ||\n Cesium.Quaternion.fromRotationMatrix(\n Cesium.Matrix4.getRotation(\n this.viewer.camera.transform,\n new Cesium.Matrix3()\n )\n );\n\n const frustum = new Cesium.PerspectiveFrustum({\n fov: Cesium.Math.toRadians(fov),\n aspectRatio: aspectRatio,\n near: near,\n far: far,\n });\n\n // 创建视锥体填充\n const fillGeometry = new Cesium.FrustumGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n vertexFormat: Cesium.VertexFormat.POSITION_ONLY,\n });\n\n const fillInstance = new Cesium.GeometryInstance({\n geometry: fillGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.fillColor || new Cesium.Color(1.0, 0.0, 0.0, 0.3)\n ),\n },\n });\n\n const fillPrimitive = new Cesium.Primitive({\n geometryInstances: fillInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n // 创建视锥体轮廓\n const outlineGeometry = new Cesium.FrustumOutlineGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n });\n\n const outlineInstance = new Cesium.GeometryInstance({\n geometry: outlineGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.outlineColor || new Cesium.Color(1.0, 1.0, 1.0, 1.0)\n ),\n },\n });\n\n const outlinePrimitive = new Cesium.Primitive({\n geometryInstances: outlineInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n this.viewer.scene.primitives.add(fillPrimitive);\n this.viewer.scene.primitives.add(outlinePrimitive);\n this.frustumPrimitives.push(fillPrimitive, outlinePrimitive);\n\n // 右键点击事件\n if (options.onRightClick && this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.setInputAction((movement: any) => {\n if (movement.position && options.onRightClick) {\n options.onRightClick(position);\n }\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n }\n } catch (error) {\n console.error('绘制视锥体时发生错误:', error);\n // 确保在出错时也清理资源\n this.clearFrustum();\n }\n }\n\n /**\n * 开始绘制线条\n */\n startDrawingLine(): void {\n this.startDrawing(\"line\");\n }\n\n /**\n * 开始绘制多边形(仅边线)\n */\n startDrawingPolygon(): void {\n this.startDrawing(\"polygon\");\n }\n\n /**\n * 开始绘制矩形\n */\n startDrawingRectangle(): void {\n this.startDrawing(\"rectangle\");\n }\n\n /**\n * 内部统一的开始绘制方法\n * @param mode 绘制模式\n */\n private startDrawing(mode: \"line\" | \"polygon\" | \"rectangle\"): void {\n this.endDrawingInternal(false); // 结束任何正在进行的绘制,但不清空已完成的实体\n\n this.drawMode = mode;\n this.isDrawing = true;\n this.tempPositions = [];\n this.tempEntities = [];\n\n this.activateDrawingHandlers();\n\n // 触发开始绘制回调\n if (this.onDrawStartCallback) {\n this.onDrawStartCallback();\n }\n }\n\n /**\n * 激活屏幕空间事件处理器\n */\n private activateDrawingHandlers(): void {\n this.deactivateDrawingHandlers(); // 确保之前的手柄已销毁\n\n this.screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(\n this.scene.canvas\n );\n\n // 左键点击添加点\n this.screenSpaceEventHandler.setInputAction(\n (click: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n if (!this.isDrawing) return;\n const cartesian = this.pickGlobePosition(click.position);\n if (cartesian) {\n this.addPoint(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.LEFT_CLICK\n );\n\n // 右键删除最后一个点\n this.screenSpaceEventHandler.setInputAction(() => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n this.removeLastPoint();\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n\n // 鼠标移动更新预览\n this.screenSpaceEventHandler.setInputAction(\n (move: Cesium.ScreenSpaceEventHandler.MotionEvent) => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n const cartesian = this.pickGlobePosition(move.endPosition);\n if (cartesian) {\n this.updatePreview(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.MOUSE_MOVE\n );\n\n // 双击结束绘制\n const mapDoubleClickAct =\n this.viewer.cesiumWidget.screenSpaceEventHandler.getInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.screenSpaceEventHandler.setInputAction(\n (dblClick: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n // 阻止 Cesium 默认的双击行为(如追踪实体)\n // Cesium.ScreenSpaceEventHandler.preventDefault(dblClick);\n if (!this.isDrawing) return;\n this.finishDrawing();\n // 恢复 Cesium 默认的双击行为\n this.viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(\n mapDoubleClickAct,\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n },\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n }\n\n /**\n * 拾取地形或椭球体上的位置\n * @param windowPosition 屏幕坐标\n * @returns 世界坐标 Cartesian3 或 null\n */\n private pickGlobePosition(\n windowPosition: Cesium.Cartesian2\n ): Cesium.Cartesian3 | null {\n // 首先尝试从地形拾取\n const ray = this.viewer.camera.getPickRay(windowPosition);\n if (ray) {\n const position = this.scene.globe.pick(ray, this.scene);\n if (Cesium.defined(position)) {\n return position;\n }\n }\n // 如果地形拾取失败,回退到椭球体拾取\n const ellipsoidPosition = this.viewer.camera.pickEllipsoid(\n windowPosition,\n this.scene.globe.ellipsoid\n );\n return ellipsoidPosition ?? null;\n }\n\n /**\n * 添加一个点到临时位置数组并创建点实体\n * @param position 世界坐标\n */\n private addPoint(position: Cesium.Cartesian3): void {\n this.tempPositions.push(position.clone());\n\n const pointEntity = this.entities.add({\n position: position.clone(),\n point: {\n pixelSize: 5,\n color: Cesium.Color.RED,\n outlineColor: Cesium.Color.WHITE,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.tempEntities.push(pointEntity);\n this.updateDrawingEntity();\n }\n\n /**\n * 删除最后一个添加的点及其相关的临时实体\n */\n private removeLastPoint(): void {\n if (this.tempPositions.length > 0) {\n this.tempPositions.pop();\n\n // 移除最后添加的点实体\n const lastPointEntity = this.tempEntities.pop();\n if (lastPointEntity) {\n this.entities.remove(lastPointEntity);\n }\n\n // 移除最后添加的线/面片段实体\n const lastLineEntity = this.tempEntities.pop();\n if (lastLineEntity) {\n this.entities.remove(lastLineEntity);\n }\n\n // 重新更新当前的绘制实体\n this.updateDrawingEntity();\n }\n }\n\n /**\n * 更新预览线/面\n * @param currentMousePosition 当前鼠标位置世界坐标\n */\n private updatePreview(currentMousePosition: Cesium.Cartesian3): void {\n this.updateDrawingEntity(currentMousePosition);\n }\n\n /**\n * 核心方法:根据当前点序列更新或创建临时的线/面实体\n * @param previewPoint 可选的预览点,用于显示动态效果\n */\n private updateDrawingEntity(previewPoint?: Cesium.Cartesian3): void {\n // 移除旧的活动实体(包括线和标签)\n this.tempEntities.forEach(entity => {\n if (entity && (entity.polyline || entity.polygon || entity.label)) {\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n\n const positions = [...this.tempPositions];\n if (previewPoint) {\n positions.push(previewPoint);\n }\n\n if (positions.length < 2) return;\n\n let activeEntity: Cesium.Entity | undefined;\n\n if (this.drawMode === \"line\") {\n // 创建主线条\n activeEntity = this.entities.add({\n polyline: {\n positions: positions,\n width: 3,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n this.tempEntities.push(activeEntity);\n\n // 为每一段添加距离标签\n for (let i = 0; i < positions.length - 1; i++) {\n const startPos = positions[i];\n const endPos = positions[i + 1];\n const distance = Cesium.Cartesian3.distance(startPos, endPos);\n const midPoint = Cesium.Cartesian3.midpoint(startPos, endPos, new Cesium.Cartesian3());\n \n const labelEntity = this.entities.add({\n position: midPoint,\n label: {\n text: `${distance.toFixed(2)} m`,\n font: \"12px sans-serif\",\n fillColor: Cesium.Color.CYAN,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 1,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -10),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.tempEntities.push(labelEntity);\n }\n\n // 添加总距离标签(在最后一个点)\n if (positions.length > 1) {\n let totalDistance = 0;\n for (let i = 1; i < positions.length; i++) {\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\n }\n \n const totalLabelEntity = this.entities.add({\n position: positions[positions.length - 1],\n label: {\n text: `总长: ${totalDistance.toFixed(2)} m`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, 20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.tempEntities.push(totalLabelEntity);\n }\n } else if (this.drawMode === \"polygon\") {\n // 绘制填充的多边形区域\n activeEntity = this.entities.add({\n polygon: {\n hierarchy: new Cesium.CallbackProperty(() => {\n return new Cesium.PolygonHierarchy(positions);\n }, false),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n activeEntity = this.entities.add({\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n\n if (activeEntity) {\n this.tempEntities.push(activeEntity);\n }\n }\n\n /**\n * 完成当前绘制操作\n */\n private finishDrawing(): void {\n if (this.tempPositions.length < (this.drawMode === \"rectangle\" ? 2 : 2)) {\n // 点数不足,取消绘制\n this.endDrawingInternal(true);\n return;\n }\n\n let finalEntity: Cesium.Entity | null = null;\n const positions = this.tempPositions.map((p) => p.clone());\n\n if (this.drawMode === \"line\") {\n finalEntity = this.entities.add({\n name: \"绘制的线\",\n polyline: {\n positions: positions,\n width: 3,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n\n // 为每一段添加距离标签\n for (let i = 0; i < positions.length - 1; i++) {\n const startPos = positions[i];\n const endPos = positions[i + 1];\n const distance = Cesium.Cartesian3.distance(startPos, endPos);\n const midPoint = Cesium.Cartesian3.midpoint(startPos, endPos, new Cesium.Cartesian3());\n \n this.entities.add({\n position: midPoint,\n label: {\n text: `${distance.toFixed(2)} m`,\n font: \"12px sans-serif\",\n fillColor: Cesium.Color.CYAN,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 1,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -10),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n\n // 添加总距离标签\n if (positions.length > 1) {\n let totalDistance = 0;\n for (let i = 1; i < positions.length; i++) {\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\n }\n \n this.entities.add({\n position: positions[positions.length - 1],\n label: {\n text: `总长: ${totalDistance.toFixed(2)} m`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, 20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n } else if (this.drawMode === \"polygon\") {\n // 绘制填充的多边形区域\n finalEntity = this.entities.add({\n name: \"绘制的多边形区域\",\n polygon: {\n hierarchy: new Cesium.PolygonHierarchy(positions),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n // 添加面积标签\n const area = this.calculatePolygonArea(positions);\n if (area > 0) {\n const center = this.calculatePolygonCenter(positions);\n this.entities.add({\n position: center,\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n finalEntity = this.entities.add({\n name: \"绘制的矩形\",\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n // 添加面积标签\n const area = this.calculateRectangleArea(rect);\n if (area > 0) {\n const rectCenter = Cesium.Rectangle.center(rect);\n this.entities.add({\n position: Cesium.Cartesian3.fromRadians(\n rectCenter.longitude,\n rectCenter.latitude\n ),\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n }\n\n // 将完成的实体存入列表\n if (finalEntity) {\n this.finishedEntities.push(finalEntity);\n }\n\n // 清理临时数据和状态\n this.endDrawingInternal(true);\n\n // 触发结束绘制回调\n if (this.onDrawEndCallback) {\n this.onDrawEndCallback(finalEntity);\n }\n }\n\n /**\n * 内部方法:重置绘图状态和清理临时数据\n * @param resetMode 是否重置绘图模式和状态标志\n */\n private endDrawingInternal(resetMode: boolean): void {\n // 清理临时实体\n this.tempEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.tempEntities = [];\n this.tempPositions = [];\n\n if (resetMode) {\n this.drawMode = null;\n this.isDrawing = false;\n this.deactivateDrawingHandlers();\n }\n }\n\n /**\n * 公共方法:结束当前绘制(如果正在进行)\n */\n endDrawing(): void {\n if (this.isDrawing) {\n this.finishDrawing();\n } else {\n // 如果没有在绘制,也执行一次清理\n this.endDrawingInternal(true);\n }\n }\n\n /**\n * 销毁事件处理器\n */\n private deactivateDrawingHandlers(): void {\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n\n /**\n * 清除所有已绘制的实体\n */\n clearAll(): void {\n // 先结束可能的绘制\n this.endDrawing();\n // 清除所有已完成的实体\n this.finishedEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.finishedEntities = [];\n }\n\n /**\n * 删除一个指定的已完成实体\n * @param entity 要删除的实体\n */\n removeEntity(entity: Cesium.Entity): void {\n const index = this.finishedEntities.indexOf(entity);\n if (index > -1) {\n this.entities.remove(entity);\n this.finishedEntities.splice(index, 1);\n if (this.onEntityRemovedCallback) {\n this.onEntityRemovedCallback(entity);\n }\n }\n }\n\n /**\n * 获取所有已完成的实体\n * @returns 实体数组\n */\n getFinishedEntities(): Cesium.Entity[] {\n return [...this.finishedEntities];\n }\n\n // --- 辅助计算函数 ---\n private calculateRectangle(\n p1: Cesium.Cartesian3,\n p2: Cesium.Cartesian3\n ): Cesium.Rectangle {\n const cartographic1 = Cesium.Cartographic.fromCartesian(p1);\n const cartographic2 = Cesium.Cartographic.fromCartesian(p2);\n const west = Math.min(cartographic1.longitude, cartographic2.longitude);\n const east = Math.max(cartographic1.longitude, cartographic2.longitude);\n const south = Math.min(cartographic1.latitude, cartographic2.latitude);\n const north = Math.max(cartographic1.latitude, cartographic2.latitude);\n return new Cesium.Rectangle(west, south, east, north);\n }\n\n private calculateRectangleArea(rect: Cesium.Rectangle): number {\n const west = rect.west;\n const south = rect.south;\n const east = rect.east;\n const north = rect.north;\n\n const width = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(east, south)\n );\n const height = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(west, north)\n );\n\n return (width * height) / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonArea(positions: Cesium.Cartesian3[]): number {\n if (positions.length < 3) return 0;\n const ellipsoid = this.scene.globe.ellipsoid;\n let area = 0;\n const len = positions.length;\n for (let i = 0; i < len; i++) {\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\n area +=\n (p2.longitude - p1.longitude) *\n (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\n }\n area = Math.abs((area * 6378137.0 * 6378137.0) / 2.0); // WGS84半径\n return area / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonCenter(\n positions: Cesium.Cartesian3[]\n ): Cesium.Cartesian3 {\n if (positions.length === 0) return Cesium.Cartesian3.ZERO;\n let x = 0,\n y = 0,\n z = 0;\n for (let i = 0; i < positions.length; i++) {\n x += positions[i].x;\n y += positions[i].y;\n z += positions[i].z;\n }\n return new Cesium.Cartesian3(\n x / positions.length,\n y / positions.length,\n z / positions.length\n );\n }\n\n // --- 回调注册 ---\n\n /**\n * 设置开始绘制时的回调函数\n * @param callback 回调函数\n */\n onDrawStart(callback: () => void): void {\n this.onDrawStartCallback = callback;\n }\n\n /**\n * 设置结束绘制时的回调函数\n * @param callback 回调函数,参数为完成的实体或null\n */\n onDrawEnd(callback: (entity: Cesium.Entity | null) => void): void {\n this.onDrawEndCallback = callback;\n }\n\n /**\n * 设置实体被移除时的回调函数\n * @param callback 回调函数,参数为被移除的实体\n */\n onEntityRemoved(callback: (entity: Cesium.Entity) => void): void {\n this.onEntityRemovedCallback = callback;\n }\n\n /**\n * 绘制监控圆形区域\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param radius 监控范围半径(米)\n * @param options 可选配置\n */\n public drawMonitoringCircle(\n longitude: number,\n latitude: number,\n height: number,\n radius: number,\n options?: {\n borderColor?: string;\n fillColor?: string;\n borderWidth?: number;\n name?: string;\n }\n ): Cesium.Entity {\n const borderColor = options?.borderColor || '#0062FF';\n const fillColor = options?.fillColor || '#0062FF';\n const borderWidth = options?.borderWidth || 2;\n const name = options?.name || '监控区域';\n\n // 创建圆形区域\n const entity = this.entities.add({\n name: name,\n position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),\n ellipse: {\n semiMajorAxis: radius,\n semiMinorAxis: radius,\n material: Cesium.Color.fromCssColorString(fillColor).withAlpha(0.27),\n outline: true,\n outlineColor: Cesium.Color.fromCssColorString(borderColor),\n outlineWidth: borderWidth,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n\n return entity;\n }\n\n /**\n * 绘制垂直线条\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param options 可选配置\n */\n public drawVerticalLine(\n longitude: number,\n latitude: number,\n height: number,\n options?: {\n color?: string;\n width?: number;\n dashPattern?: number;\n name?: string;\n groundHeight?: number;\n }\n ): Cesium.Entity {\n const color = options?.color || '#0062FF';\n const width = options?.width || 2;\n const dashPattern = options?.dashPattern || 0x00FF00FF;\n const name = options?.name || '垂直线条';\n const groundHeight = options?.groundHeight || 0;\n\n // 计算地面位置\n const groundPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude, groundHeight);\n const topPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);\n\n // 创建垂直线条\n const entity = this.entities.add({\n name: name,\n polyline: {\n positions: [groundPosition, topPosition],\n width: width,\n material: new Cesium.PolylineDashMaterialProperty({\n color: Cesium.Color.fromCssColorString(color),\n }),\n clampToGround: false,\n },\n });\n\n return entity;\n }\n\n /**\n * 销毁工具,清理所有事件监听器\n */\n destroy(): void {\n this.deactivateDrawingHandlers();\n this.clearFrustum(); // 清理视锥体相关资源\n // 可以选择不清除实体,由用户决定\n // this.clearAll();\n }\n}\n\n// 为了在 HTML 中通过 <script type=\"module\"> 或打包工具使用\n// @ts-ignore\nwindow.DrawHelper = DrawHelper;\n\nexport default DrawHelper;\n","import * as Cesium from 'cesium';\r\nimport type { Viewer, Cartesian3, Cartographic } from 'cesium';\r\nimport DrawHelper from './CesiumMapHelper';\r\n\r\n// 工具栏配置接口\r\nexport interface ToolbarConfig {\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\r\n buttonSize?: number;\r\n buttonSpacing?: number;\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderRadius?: number;\r\n borderWidth?: number;\r\n boxShadow?: string;\r\n zIndex?: number;\r\n buttons?: CustomButtonConfig[];\r\n}\r\n\r\n// 按钮配置接口\r\nexport interface ButtonConfig {\r\n id: string;\r\n icon: string;\r\n title: string;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n}\r\n\r\n// 自定义按钮配置接口\r\nexport interface CustomButtonConfig {\r\n id: string;\r\n icon: string | HTMLElement;\r\n title: string;\r\n enabled?: boolean;\r\n visible?: boolean;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n onClick?: (buttonId: string, buttonElement: HTMLElement) => void;\r\n}\r\n\r\n// 搜索回调接口\r\nexport interface SearchCallback {\r\n onSearch?: (query: string) => Promise<SearchResult[]>;\r\n onSelect?: (result: SearchResult) => void;\r\n onSearchInput?: (query: string, container: HTMLElement) => void;\r\n onSearchResults?: (results: SearchResult[], container: HTMLElement) => void;\r\n}\r\n\r\n// 搜索结果接口\r\nexport interface SearchResult {\r\n name: string;\r\n address: string;\r\n longitude: number;\r\n latitude: number;\r\n height?: number;\r\n}\r\n\r\n// 测量回调接口\r\nexport interface MeasurementCallback {\r\n onDistanceComplete?: (positions: Cartesian3[], distance: number) => void;\r\n onAreaComplete?: (positions: Cartesian3[], area: number) => void;\r\n onClear?: () => void;\r\n}\r\n\r\n// 缩放回调接口\r\nexport interface ZoomCallback {\r\n onZoomIn?: (beforeLevel: number, afterLevel: number) => void;\r\n onZoomOut?: (beforeLevel: number, afterLevel: number) => void;\r\n}\r\n\r\n// 地图类型接口\r\nexport interface MapType {\r\n id: string;\r\n name: string;\r\n thumbnail: string;\r\n provider: Cesium.ImageryProvider;\r\n}\r\n\r\n/**\r\n * Cesium地图工具栏类\r\n * 提供搜索、测量、2D/3D切换、图层切换、定位、缩放、全屏等功能\r\n */\r\nexport class CesiumMapToolbar {\r\n private viewer: Viewer;\r\n private drawHelper: DrawHelper;\r\n private container: HTMLElement;\r\n private toolbarElement!: HTMLElement;\r\n private config: ToolbarConfig;\r\n private searchCallback?: SearchCallback;\r\n private measurementCallback?: MeasurementCallback;\r\n private zoomCallback?: ZoomCallback;\r\n private initialCenter?: { longitude: number; latitude: number; height: number };\r\n private isFullscreen: boolean = false;\r\n private currentMapType: string = 'imagery';\r\n\r\n // 地图类型配置\r\n private mapTypes: MapType[] = [\r\n {\r\n id: 'normal',\r\n name: '天地图-普通',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: '3d',\r\n name: '天地图-三维',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'imagery',\r\n name: '天地图-影像',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'terrain',\r\n name: '天地图-地形',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n }\r\n ];\r\n\r\n constructor(\r\n viewer: Viewer,\r\n container: HTMLElement,\r\n config: ToolbarConfig = {},\r\n callbacks?: {\r\n search?: SearchCallback;\r\n measurement?: MeasurementCallback;\r\n zoom?: ZoomCallback;\r\n },\r\n initialCenter?: { longitude: number; latitude: number; height: number }\r\n ) {\r\n this.viewer = viewer;\r\n this.container = container;\r\n this.config = {\r\n position: 'bottom-right',\r\n buttonSize: 40,\r\n buttonSpacing: 8,\r\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\r\n borderColor: '#e0e0e0',\r\n borderRadius: 6,\r\n boxShadow: '0 2px 10px rgba(0, 0, 0, 0.1)',\r\n zIndex: 1000,\r\n ...config\r\n };\r\n this.searchCallback = callbacks?.search;\r\n this.measurementCallback = callbacks?.measurement;\r\n this.zoomCallback = callbacks?.zoom;\r\n\r\n // 设置初始中心点\r\n this.initialCenter = initialCenter;\r\n\r\n // 初始化绘图助手\r\n this.drawHelper = new DrawHelper(viewer);\r\n this.setupDrawHelperCallbacks();\r\n\r\n // 创建工具栏\r\n this.createToolbar();\r\n }\r\n\r\n /**\r\n * 设置初始中心点\r\n */\r\n public setInitialCenter(center: { longitude: number; latitude: number; height: number }): void {\r\n this.initialCenter = center;\r\n }\r\n\r\n /**\r\n * 获取初始中心点\r\n */\r\n public getInitialCenter(): { longitude: number; latitude: number; height: number } | undefined {\r\n return this.initialCenter;\r\n }\r\n\r\n /**\r\n * 复位到初始位置(公共方法)\r\n */\r\n public resetToInitialLocation(): void {\r\n this.resetLocation();\r\n }\r\n\r\n /**\r\n * 更新按钮配置\r\n */\r\n public updateButtonConfig(buttonId: string, config: Partial<CustomButtonConfig>): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (!button) return;\r\n\r\n // 更新按钮属性\r\n if (config.title) button.title = config.title;\r\n if (config.icon) this.setButtonIcon(button, config.icon);\r\n if (config.size) {\r\n button.style.width = `${config.size}px`;\r\n button.style.height = `${config.size}px`;\r\n }\r\n if (config.color) button.style.background = config.color;\r\n }\r\n\r\n /**\r\n * 添加自定义按钮\r\n */\r\n public addCustomButton(config: CustomButtonConfig): void {\r\n const buttonConfig: ButtonConfig = {\r\n id: config.id,\r\n icon: typeof config.icon === 'string' ? config.icon : '',\r\n title: config.title,\r\n size: config.size,\r\n color: config.color,\r\n hoverColor: config.hoverColor,\r\n activeColor: config.activeColor\r\n };\r\n\r\n const buttonElement = this.createButton(buttonConfig);\r\n this.toolbarElement.appendChild(buttonElement);\r\n\r\n // 更新配置\r\n if (!this.config.buttons) {\r\n this.config.buttons = [];\r\n }\r\n this.config.buttons.push(config);\r\n }\r\n\r\n /**\r\n * 移除按钮\r\n */\r\n public removeButton(buttonId: string): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (button && button.parentNode) {\r\n button.parentNode.removeChild(button);\r\n }\r\n\r\n // 从配置中移除\r\n if (this.config.buttons) {\r\n this.config.buttons = this.config.buttons.filter(btn => btn.id !== buttonId);\r\n }\r\n }\r\n\r\n /**\r\n * 获取按钮元素\r\n */\r\n public getButtonElement(buttonId: string): HTMLElement | null {\r\n return this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n }\r\n\r\n /**\r\n * 设置绘图助手回调\r\n */\r\n private setupDrawHelperCallbacks(): void {\r\n this.drawHelper.onDrawStart(() => {\r\n console.log('开始绘制');\r\n });\r\n\r\n this.drawHelper.onDrawEnd((entity) => {\r\n if (entity) {\r\n console.log('绘制完成', entity);\r\n // 根据绘制类型触发相应回调\r\n if (entity.polyline) {\r\n // 测距完成\r\n const positions = entity.polyline.positions?.getValue(Cesium.JulianDate.now()) as Cartesian3[];\r\n if (positions && this.measurementCallback?.onDistanceComplete) {\r\n let totalDistance = 0;\r\n for (let i = 1; i < positions.length; i++) {\r\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\r\n }\r\n this.measurementCallback.onDistanceComplete(positions, totalDistance);\r\n }\r\n } else if (entity.polygon) {\r\n // 测面积完成\r\n const positions = entity.polygon.hierarchy?.getValue(Cesium.JulianDate.now()) as Cesium.PolygonHierarchy;\r\n if (positions && this.measurementCallback?.onAreaComplete) {\r\n // 计算面积\r\n const area = this.calculatePolygonArea(positions.positions);\r\n this.measurementCallback.onAreaComplete(positions.positions, area);\r\n }\r\n }\r\n }\r\n });\r\n\r\n this.drawHelper.onEntityRemoved((entity) => {\r\n console.log('实体被移除', entity);\r\n });\r\n }\r\n\r\n /**\r\n * 计算多边形面积\r\n */\r\n private calculatePolygonArea(positions: Cartesian3[]): number {\r\n if (positions.length < 3) return 0;\r\n \r\n const ellipsoid = this.viewer.scene.globe.ellipsoid;\r\n let area = 0;\r\n const len = positions.length;\r\n \r\n for (let i = 0; i < len; i++) {\r\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\r\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\r\n area += (p2.longitude - p1.longitude) * (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\r\n }\r\n \r\n area = Math.abs(area * 6378137.0 * 6378137.0 / 2.0);\r\n return area / 1e6; // 转换为平方公里\r\n }\r\n\r\n /**\r\n * 创建工具栏\r\n */\r\n private createToolbar(): void {\r\n this.toolbarElement = document.createElement('div');\r\n this.toolbarElement.className = 'cesium-map-toolbar';\r\n this.toolbarElement.style.cssText = `\r\n position: absolute;\r\n ${this.config.position?.includes('right') ? 'right' : 'left'}: 10px;\r\n ${this.config.position?.includes('bottom') ? 'bottom' : 'top'}: 10px;\r\n background: ${this.config.backgroundColor};\r\n border: ${this.config.borderWidth}px solid ${this.config.borderColor};\r\n border-radius: ${this.config.borderRadius}px;\r\n box-shadow: ${this.config.boxShadow};\r\n padding: 8px;\r\n z-index: ${this.config.zIndex};\r\n display: flex;\r\n flex-direction: column;\r\n gap: ${this.config.buttonSpacing}px;\r\n `;\r\n\r\n // 获取按钮配置\r\n const buttons = this.getButtonConfigs();\r\n\r\n buttons.forEach(button => {\r\n const buttonElement = this.createButton(button);\r\n this.toolbarElement.appendChild(buttonElement);\r\n });\r\n\r\n this.container.appendChild(this.toolbarElement);\r\n }\r\n\r\n /**\r\n * 获取按钮配置\r\n */\r\n private getButtonConfigs(): ButtonConfig[] {\r\n // 默认按钮配置\r\n const defaultButtons: ButtonConfig[] = [\r\n { id: 'search', icon: '🔍', title: '搜索' },\r\n { id: 'measure', icon: '📏', title: '测量' },\r\n { id: 'view2d3d', icon: '2D', title: '2D或3D' },\r\n { id: 'layers', icon: '📚', title: '图层切换' },\r\n { id: 'location', icon: '🎯', title: '定位' },\r\n { id: 'zoom-in', icon: '🔍+', title: '放大' },\r\n { id: 'zoom-out', icon: '🔍-', title: '缩小' },\r\n { id: 'fullscreen', icon: '⛶', title: '全屏' }\r\n ];\r\n\r\n // 如果用户提供了自定义按钮配置,则使用自定义配置\r\n if (this.config.buttons && this.config.buttons.length > 0) {\r\n return this.config.buttons.map(customButton => ({\r\n id: customButton.id,\r\n icon: typeof customButton.icon === 'string' ? customButton.icon : '',\r\n title: customButton.title,\r\n size: customButton.size,\r\n color: customButton.color,\r\n hoverColor: customButton.hoverColor,\r\n activeColor: customButton.activeColor\r\n }));\r\n }\r\n\r\n return defaultButtons;\r\n }\r\n\r\n /**\r\n * 创建按钮\r\n */\r\n private createButton(config: ButtonConfig): HTMLElement {\r\n const button = document.createElement('div');\r\n button.className = 'cesium-toolbar-button';\r\n button.setAttribute('data-tool', config.id);\r\n button.title = config.title;\r\n \r\n const buttonSize = config.size || this.config.buttonSize;\r\n const buttonColor = config.color || 'rgba(66, 133, 244, 0.4)';\r\n const buttonHoverColor = config.hoverColor || 'rgba(51, 103, 214, 0.9)';\r\n \r\n button.style.cssText = `\r\n width: ${buttonSize}px;\r\n height: ${buttonSize}px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: ${buttonColor};\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n font-weight: bold;\r\n transition: all 0.2s ease;\r\n user-select: none;\r\n position: relative;\r\n `;\r\n\r\n // 设置图标内容\r\n this.setButtonIcon(button, config.icon);\r\n\r\n // 悬停效果\r\n button.addEventListener('mouseenter', () => {\r\n button.style.background = buttonHoverColor;\r\n button.style.transform = 'scale(1.05)';\r\n });\r\n\r\n button.addEventListener('mouseleave', () => {\r\n button.style.background = buttonColor;\r\n button.style.transform = 'scale(1)';\r\n });\r\n\r\n // 处理点击事件\r\n this.setupButtonEvents(button, config);\r\n\r\n return button;\r\n }\r\n\r\n /**\r\n * 设置按钮图标\r\n */\r\n private setButtonIcon(button: HTMLElement, icon: string | HTMLElement): void {\r\n if (typeof icon === 'string') {\r\n button.innerHTML = icon;\r\n } else if (icon instanceof HTMLElement) {\r\n button.innerHTML = '';\r\n button.appendChild(icon);\r\n }\r\n }\r\n\r\n /**\r\n * 设置按钮事件\r\n */\r\n private setupButtonEvents(button: HTMLElement, config: ButtonConfig): void {\r\n // 查找自定义按钮配置\r\n const customButton = this.config.buttons?.find(btn => btn.id === config.id);\r\n \r\n if (customButton?.onClick) {\r\n // 自定义按钮点击事件\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n customButton.onClick!(config.id, button);\r\n });\r\n } else if (!['search', 'measure', 'layers'].includes(config.id)) {\r\n // 默认按钮点击事件(除了搜索、测量、图层切换按钮)\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.handleButtonClick(config.id, button);\r\n });\r\n } else {\r\n // 搜索、测量、图层切换按钮使用hover事件\r\n button.addEventListener('mouseenter', () => {\r\n this.handleButtonClick(config.id, button);\r\n });\r\n \r\n // 添加鼠标离开事件来关闭菜单\r\n button.addEventListener('mouseleave', () => {\r\n this.closeMenuOnButtonLeave(config.id);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 按钮鼠标离开时关闭菜单\r\n */\r\n private closeMenuOnButtonLeave(buttonId: string): void {\r\n // 延迟关闭,给用户时间移动到菜单上\r\n setTimeout(() => {\r\n switch (buttonId) {\r\n case 'search':\r\n const searchContainer = this.toolbarElement.querySelector('.search-container');\r\n if (searchContainer && !searchContainer.matches(':hover')) {\r\n searchContainer.remove();\r\n }\r\n break;\r\n case 'measure':\r\n const measureMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (measureMenu && !measureMenu.matches(':hover')) {\r\n measureMenu.remove();\r\n }\r\n break;\r\n case 'layers':\r\n const layersMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (layersMenu && !layersMenu.matches(':hover')) {\r\n layersMenu.remove();\r\n }\r\n break;\r\n }\r\n }, 100); // 100ms延迟,给用户时间移动到菜单\r\n }\r\n\r\n /**\r\n * 处理按钮点击\r\n */\r\n private handleButtonClick(buttonId: string, buttonElement: HTMLElement): void {\r\n switch (buttonId) {\r\n case 'search':\r\n this.toggleSearch(buttonElement);\r\n break;\r\n case 'measure':\r\n this.toggleMeasurement(buttonElement);\r\n break;\r\n case 'view2d3d':\r\n this.toggle2D3D(buttonElement);\r\n break;\r\n case 'layers':\r\n this.toggleLayers(buttonElement);\r\n break;\r\n case 'location':\r\n this.resetLocation();\r\n break;\r\n case 'zoom-in':\r\n this.zoomIn();\r\n break;\r\n case 'zoom-out':\r\n this.zoomOut();\r\n break;\r\n case 'fullscreen':\r\n this.toggleFullscreen();\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换搜索功能\r\n */\r\n private toggleSearch(buttonElement: HTMLElement): void {\r\n const existingSearch = this.toolbarElement.querySelector('.search-container');\r\n if (existingSearch) {\r\n return; // 如果搜索框已存在,不重复创建\r\n }\r\n\r\n const searchContainer = document.createElement('div');\r\n searchContainer.className = 'search-container';\r\n searchContainer.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 8px;\r\n min-width: 200px;\r\n z-index: 1001;\r\n `;\r\n\r\n const searchInput = document.createElement('input');\r\n searchInput.type = 'text';\r\n searchInput.placeholder = '请输入地址';\r\n searchInput.style.cssText = `\r\n padding: 6px 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n outline: none;\r\n `;\r\n\r\n const resultsContainer = document.createElement('div');\r\n resultsContainer.className = 'search-results';\r\n resultsContainer.style.cssText = `\r\n margin-top: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n `;\r\n\r\n searchContainer.appendChild(searchInput);\r\n searchContainer.appendChild(resultsContainer);\r\n\r\n // 插入到按钮前面\r\n this.toolbarElement.insertBefore(searchContainer, buttonElement);\r\n\r\n // 搜索功能\r\n let searchTimeout: ReturnType<typeof setTimeout>;\r\n searchInput.addEventListener('input', () => {\r\n clearTimeout(searchTimeout);\r\n const query = searchInput.value.trim();\r\n \r\n // 如果用户提供了自定义搜索输入处理逻辑\r\n if (this.searchCallback?.onSearchInput) {\r\n this.searchCallback.onSearchInput(query, resultsContainer);\r\n return;\r\n }\r\n \r\n if (query.length < 2) {\r\n resultsContainer.innerHTML = '';\r\n return;\r\n }\r\n\r\n searchTimeout = setTimeout(async () => {\r\n if (this.searchCallback?.onSearch) {\r\n try {\r\n const results = await this.searchCallback.onSearch(query);\r\n this.displaySearchResults(results, resultsContainer);\r\n } catch (error) {\r\n console.error('搜索失败:', error);\r\n resultsContainer.innerHTML = '<div style=\"padding: 8px; color: #666;\">搜索失败</div>';\r\n }\r\n } else {\r\n // 默认搜索逻辑\r\n this.performDefaultSearch(query, resultsContainer);\r\n }\r\n }, 300);\r\n });\r\n\r\n // 鼠标离开搜索框区域时关闭\r\n const closeSearch = () => {\r\n searchContainer.remove();\r\n };\r\n \r\n // 监听搜索框的鼠标离开事件\r\n searchContainer.addEventListener('mouseleave', closeSearch);\r\n }\r\n\r\n /**\r\n * 显示搜索结果\r\n */\r\n private displaySearchResults(results: SearchResult[], container: HTMLElement): void {\r\n // 如果用户提供了自定义搜索结果处理逻辑\r\n if (this.searchCallback?.onSearchResults) {\r\n this.searchCallback.onSearchResults(results, container);\r\n return;\r\n }\r\n\r\n // 默认搜索结果显示逻辑\r\n container.innerHTML = '';\r\n \r\n if (results.length === 0) {\r\n container.innerHTML = '<div style=\"padding: 8px; color: #666;\">未找到相关地址</div>';\r\n return;\r\n }\r\n\r\n results.forEach(result => {\r\n const resultItem = document.createElement('div');\r\n resultItem.style.cssText = `\r\n padding: 8px;\r\n border-bottom: 1px solid #f0f0f0;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n resultItem.innerHTML = `\r\n <div style=\"font-weight: bold; margin-bottom: 2px;\">${result.name}</div>\r\n <div style=\"font-size: 12px; color: #666;\">${result.address}</div>\r\n `;\r\n\r\n resultItem.addEventListener('mouseenter', () => {\r\n resultItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n resultItem.addEventListener('mouseleave', () => {\r\n resultItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n resultItem.addEventListener('click', () => {\r\n this.selectSearchResult(result);\r\n container.parentElement?.remove();\r\n });\r\n\r\n container.appendChild(resultItem);\r\n });\r\n }\r\n\r\n /**\r\n * 选择搜索结果\r\n */\r\n private selectSearchResult(result: SearchResult): void {\r\n // 飞行到指定位置\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n result.longitude,\r\n result.latitude,\r\n result.height || 1000\r\n ),\r\n duration: 1.0\r\n });\r\n\r\n // 触发回调\r\n if (this.searchCallback?.onSelect) {\r\n this.searchCallback.onSelect(result);\r\n }\r\n }\r\n\r\n /**\r\n * 默认搜索逻辑\r\n */\r\n private performDefaultSearch(query: string, container: HTMLElement): void {\r\n // 模拟搜索结果\r\n const mockResults: SearchResult[] = [\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n }\r\n ];\r\n\r\n this.displaySearchResults(mockResults, container);\r\n }\r\n\r\n /**\r\n * 切换测量功能\r\n */\r\n private toggleMeasurement(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'measurement-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 4px 0;\r\n min-width: 120px;\r\n z-index: 1001;\r\n `;\r\n\r\n const menuItems = [\r\n { id: 'measure-area', text: '测面积', icon: '📐' },\r\n { id: 'measure-distance', text: '测距', icon: '📏' },\r\n { id: 'clear-measurement', text: '清除', icon: '🗑️' }\r\n ];\r\n\r\n menuItems.forEach(item => {\r\n const menuItem = document.createElement('div');\r\n menuItem.style.cssText = `\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n menuItem.innerHTML = `${item.icon} ${item.text}`;\r\n\r\n menuItem.addEventListener('mouseenter', () => {\r\n menuItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n menuItem.addEventListener('mouseleave', () => {\r\n menuItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n menuItem.addEventListener('click', () => {\r\n this.handleMeasurementAction(item.id);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(menuItem);\r\n });\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 处理测量操作\r\n */\r\n private handleMeasurementAction(action: string): void {\r\n switch (action) {\r\n case 'measure-area':\r\n this.drawHelper.startDrawingPolygon();\r\n break;\r\n case 'measure-distance':\r\n this.drawHelper.startDrawingLine();\r\n break;\r\n case 'clear-measurement':\r\n this.drawHelper.clearAll();\r\n if (this.measurementCallback?.onClear) {\r\n this.measurementCallback.onClear();\r\n }\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换2D/3D视图\r\n */\r\n private toggle2D3D(buttonElement: HTMLElement): void {\r\n const currentMode = this.viewer.scene.mode;\r\n const targetMode = currentMode === Cesium.SceneMode.SCENE3D \r\n ? Cesium.SceneMode.SCENE2D \r\n : Cesium.SceneMode.SCENE3D;\r\n \r\n this.viewer.scene.mode = targetMode;\r\n \r\n // 更新按钮文本\r\n buttonElement.innerHTML = targetMode === Cesium.SceneMode.SCENE3D ? '3D' : '2D';\r\n }\r\n\r\n /**\r\n * 切换图层\r\n */\r\n private toggleLayers(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'layers-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 6px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n padding: 12px;\r\n min-width: 220px;\r\n max-width: 280px;\r\n z-index: 1001;\r\n display: flex;\r\n flex-direction: column;\r\n `;\r\n\r\n // 地图类型选择\r\n const mapTypeSection = document.createElement('div');\r\n mapTypeSection.style.cssText = `\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n `;\r\n mapTypeSection.innerHTML = '<div style=\"font-weight: bold; margin-bottom: 8px; color: #333; font-size: 14px;\">地图类型</div>';\r\n \r\n this.mapTypes.forEach(mapType => {\r\n const mapTypeItem = document.createElement('div');\r\n mapTypeItem.style.cssText = `\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n width: 100%;\r\n box-sizing: border-box;\r\n ${mapType.id === this.currentMapType ? 'background-color: #e3f2fd;' : ''}\r\n `;\r\n\r\n const thumbnail = document.createElement('img');\r\n thumbnail.src = mapType.thumbnail;\r\n thumbnail.style.cssText = `\r\n width: 24px; \r\n height: 24px; \r\n border-radius: 3px;\r\n flex-shrink: 0;\r\n `;\r\n\r\n const label = document.createElement('span');\r\n label.textContent = mapType.name;\r\n label.style.cssText = `\r\n font-size: 14px;\r\n color: #333;\r\n flex: 1;\r\n `;\r\n\r\n const checkmark = document.createElement('span');\r\n if (mapType.id === this.currentMapType) {\r\n checkmark.textContent = '✓';\r\n checkmark.style.cssText = `\r\n color: #1976d2; \r\n font-weight: bold; \r\n font-size: 16px;\r\n flex-shrink: 0;\r\n `;\r\n }\r\n\r\n mapTypeItem.appendChild(thumbnail);\r\n mapTypeItem.appendChild(label);\r\n mapTypeItem.appendChild(checkmark);\r\n\r\n mapTypeItem.addEventListener('mouseenter', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = '#f5f5f5';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('mouseleave', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = 'transparent';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('click', () => {\r\n this.switchMapType(mapType.id);\r\n menu.remove();\r\n });\r\n\r\n mapTypeSection.appendChild(mapTypeItem);\r\n });\r\n\r\n menu.appendChild(mapTypeSection);\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 切换地图类型\r\n */\r\n private switchMapType(mapTypeId: string): void {\r\n const mapType = this.mapTypes.find(mt => mt.id === mapTypeId);\r\n if (!mapType) return;\r\n\r\n // 移除当前图层\r\n this.viewer.imageryLayers.removeAll();\r\n \r\n // 添加新图层\r\n this.viewer.imageryLayers.addImageryProvider(mapType.provider);\r\n \r\n this.currentMapType = mapTypeId;\r\n }\r\n\r\n /**\r\n * 复位到初始位置\r\n */\r\n private resetLocation(): void {\r\n if (!this.initialCenter) {\r\n console.warn('未设置初始中心点,无法执行复位操作');\r\n return;\r\n }\r\n\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n this.initialCenter.longitude,\r\n this.initialCenter.latitude,\r\n this.initialCenter.height\r\n ),\r\n duration: 1.0\r\n });\r\n }\r\n\r\n /**\r\n * 放大\r\n */\r\n private zoomIn(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomIn(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomIn) {\r\n this.zoomCallback.onZoomIn(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 缩小\r\n */\r\n private zoomOut(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomOut(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomOut) {\r\n this.zoomCallback.onZoomOut(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 切换全屏\r\n */\r\n private toggleFullscreen(): void {\r\n if (!this.isFullscreen) {\r\n this.enterFullscreen();\r\n } else {\r\n this.exitFullscreen();\r\n }\r\n }\r\n\r\n /**\r\n * 进入全屏\r\n */\r\n private enterFullscreen(): void {\r\n const container = this.viewer.container;\r\n \r\n if (container.requestFullscreen) {\r\n container.requestFullscreen();\r\n } else if ((container as any).webkitRequestFullscreen) {\r\n (container as any).webkitRequestFullscreen();\r\n } else if ((container as any).msRequestFullscreen) {\r\n (container as any).msRequestFullscreen();\r\n }\r\n\r\n this.isFullscreen = true;\r\n \r\n // 监听全屏状态变化\r\n const fullscreenChange = () => {\r\n if (!document.fullscreenElement && \r\n !(document as any).webkitFullscreenElement && \r\n !(document as any).msFullscreenElement) {\r\n this.isFullscreen = false;\r\n document.removeEventListener('fullscreenchange', fullscreenChange);\r\n document.removeEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.removeEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n };\r\n\r\n document.addEventListener('fullscreenchange', fullscreenChange);\r\n document.addEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.addEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n\r\n /**\r\n * 退出全屏\r\n */\r\n private exitFullscreen(): void {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if ((document as any).webkitExitFullscreen) {\r\n (document as any).webkitExitFullscreen();\r\n } else if ((document as any).msExitFullscreen) {\r\n (document as any).msExitFullscreen();\r\n }\r\n\r\n this.isFullscreen = false;\r\n }\r\n\r\n /**\r\n * 销毁工具栏\r\n */\r\n destroy(): void {\r\n if (this.toolbarElement && this.toolbarElement.parentNode) {\r\n this.toolbarElement.parentNode.removeChild(this.toolbarElement);\r\n }\r\n this.drawHelper.destroy();\r\n }\r\n}\r\n","import * as Cesium from 'cesium'\nimport { Ion, Viewer, createWorldTerrainAsync, Terrain, Cartesian3, SampledPositionProperty, TerrainProvider } from 'cesium'\nimport type { Entity, Viewer as CesiumViewer, EntityCollection } from 'cesium'\n\n\ninterface InitOptions {\n terrain: Terrain, // 地形\n terrainProvider?: TerrainProvider // 地形提供者\n mapType?: string // 地图类型,默认为天地图\n imageryProvider?: Cesium.UrlTemplateImageryProvider // 自定义影像图层提供r\n imageryLayers?: Cesium.ImageryLayerCollection // 自定义影像图层集合\n terrainShadows?: Cesium.ShadowMode // 地形阴影\n contextOptions?: Cesium.ContextOptions // 上下文选项\n scene3DOnly?: boolean // 是否只使用3D场景\n selectionIndicator?: boolean // 选择指示器\n navigationHelpButton?: boolean // 导航帮助按钮\n fullscreenButton?: boolean // 全屏按钮\n geocoder?: boolean // 地理编码器\n homeButton?: boolean // 主页按钮\n infoBox?: boolean // 信息框\n vrButton?: boolean // VR按钮\n sceneModePicker?: boolean // 场景模式选择器\n timeline?: boolean // 时间轴\n animation?: boolean // 动画\n baseLayerPicker?: boolean // 基础图层选择器\n navigationInstructionsInitiallyVisible?: boolean // 导航指令初始可见\n clock?: Cesium.Clock // 时钟\n sceneMode?: Cesium.SceneMode // 场景模式\n screenSpaceEventHandler?: Cesium.ScreenSpaceEventHandler // 屏幕空间事件处理器\n useDefaultRenderLoop?: boolean // 使用默认渲染循环\n targetFrameRate?: number // 目标帧率\n showRenderLoopErrors?: boolean // 显示渲染循环错误\n automaticallyTrackDataSourceClocks?: boolean // 自动跟踪数据源时钟\n dataSources?: Cesium.DataSourceCollection // 数据源集合\n creationTime?: number // 创建时间\n useBrowserRecommendedResolution?: boolean // 使用浏览器推荐分辨率\n resolutionScale?: number // 分辨率缩放\n orderIndependentTransparency?: boolean // 无序透明度\n shadows?: boolean // 阴影\n terrainExaggeration?: number // 地形夸张系数\n maximumScreenSpaceError?: number // 最大屏幕空间误差\n maximumNumberOfLoadedTiles?: number // 最大加载瓦片数量\n}\n\ninterface MapCenter {\n latitude: number\n longitude: number\n height: number,\n pitch?: number\n heading?: number\n}\n\ninterface TianDiMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\ninterface GaoDeMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\n\nexport function createTianDiMap(): TianDiMap {\n return {\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n }\n}\n\nexport function createGaoDeMap(): Cesium.UrlTemplateImageryProvider {\n return new Cesium.UrlTemplateImageryProvider({\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n })\n}\n\nexport async function initCesium(\n containerId: string,\n options: InitOptions,\n mapCenter: MapCenter = { longitude: 120.2052342, latitude: 30.2489634, height: 1000, pitch: -60, heading: 0 }\n): Promise<{ viewer: CesiumViewer; initialCenter: MapCenter }> {\n Ion.defaultAccessToken = (import.meta as any).env.VITE_CESIUM_TOKEN\n const viewer = new Viewer(containerId, {\n timeline: false,\n animation: false,\n baseLayerPicker: false,\n ...options\n })\n // 地形提供者\n if (!options.terrainProvider && !options.terrain) {\n viewer.terrainProvider = await createWorldTerrainAsync()\n }\n // 添加高德图影像图层\n if (options.mapType === 'gaode') {\n viewer.imageryLayers.removeAll();\n viewer.imageryLayers.addImageryProvider(createGaoDeMap());\n }\n if (mapCenter) {\n // 设置初始视角为中国区域 (经度, 纬度, 高度)\n viewer.camera.flyTo({\n destination: Cesium.Cartesian3.fromDegrees(mapCenter.longitude, mapCenter.latitude, mapCenter.height), // 中国中心坐标\n orientation: {\n heading: Cesium.Math.toRadians(mapCenter.heading || 0), // 方向角度\n pitch: Cesium.Math.toRadians(mapCenter.pitch || -30), // 俯\n }\n });\n }\n (viewer.cesiumWidget.creditContainer as HTMLElement).style.display = 'none';\n return { viewer, initialCenter: mapCenter }\n}","// VMap Cesium Toolbar Plugin\r\n// 导出主要类和接口\r\n\r\n// 核心类\r\nexport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nexport { default as DrawHelper } from './libs/CesiumMapHelper';\r\nexport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 类型定义\r\nexport type {\r\n ToolbarConfig,\r\n ButtonConfig,\r\n CustomButtonConfig,\r\n SearchCallback,\r\n SearchResult,\r\n MeasurementCallback,\r\n ZoomCallback,\r\n MapType\r\n} from './libs/CesiumMapToolbar';\r\n\r\nexport type {\r\n FrustumOptions,\r\n OverlayOptions\r\n} from './libs/CesiumMapModel';\r\n\r\n// 导入用于默认导出\r\nimport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nimport DrawHelper from './libs/CesiumMapHelper';\r\nimport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 默认导出\r\nexport default {\r\n CesiumMapToolbar,\r\n DrawHelper,\r\n initCesium\r\n};\r\n"],"names":["DrawHelper","viewer","Cesium","primitive","options","fov","aspectRatio","near","far","position","orientation","frustum","fillGeometry","fillInstance","fillPrimitive","outlineGeometry","outlineInstance","outlinePrimitive","movement","error","mode","click","cartesian","move","mapDoubleClickAct","dblClick","windowPosition","ray","pointEntity","lastPointEntity","lastLineEntity","currentMousePosition","previewPoint","entity","positions","activeEntity","i","startPos","endPos","distance","midPoint","labelEntity","totalDistance","totalLabelEntity","rect","finalEntity","p","area","center","rectCenter","resetMode","index","p1","p2","cartographic1","cartographic2","west","east","south","north","width","height","ellipsoid","len","x","y","z","callback","longitude","latitude","radius","borderColor","fillColor","borderWidth","name","color","groundHeight","groundPosition","topPosition","CesiumMapToolbar","container","config","callbacks","initialCenter","buttonId","button","buttonConfig","buttonElement","btn","defaultButtons","customButton","buttonSize","buttonColor","buttonHoverColor","icon","e","searchContainer","measureMenu","layersMenu","searchInput","resultsContainer","searchTimeout","query","results","closeSearch","result","resultItem","mockResults","menu","item","menuItem","closeMenu","action","targetMode","mapTypeSection","mapType","mapTypeItem","thumbnail","label","checkmark","mapTypeId","mt","beforeLevel","afterLevel","fullscreenChange","createGaoDeMap","initCesium","containerId","mapCenter","Ion","Viewer","createWorldTerrainAsync"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/libs/CesiumMapHelper.ts","../src/libs/CesiumMapToolbar.ts","../src/libs/CesiumMapLoader.ts","../src/index.ts"],"sourcesContent":["import * as Cesium from \"cesium\";\nimport type { Primitive } from \"cesium\";\nimport type { FrustumOptions } from \"./CesiumMapModel\";\n/**\n * Cesium 绘图辅助工具类\n * 支持绘制点、线、多边形、矩形,并提供编辑和删除功能\n * 适用于 Cesium 1.132.0\n */\nclass DrawHelper {\n private viewer: Cesium.Viewer;\n private scene: Cesium.Scene;\n private entities: Cesium.EntityCollection;\n private frustumPrimitives: Primitive[] = [];\n\n // 绘图状态和数据\n private drawMode: \"line\" | \"polygon\" | \"rectangle\" | null = null;\n private isDrawing: boolean = false;\n private tempPositions: Cesium.Cartesian3[] = [];\n private tempEntities: Cesium.Entity[] = []; // 临时实体,用于绘制过程中\n private tempLabelEntities: Cesium.Entity[] = []; // 临时标签实体\n private finishedEntities: Cesium.Entity[] = []; // 已完成的实体\n private finishedLabelEntities: Cesium.Entity[] = []; // 已完成的标签实体\n private finishedPointEntities: Cesium.Entity[] = []; // 已完成的点实体\n private publicEntities: Cesium.Entity[] = []; // 通过公共方法创建的实体\n private _doubleClickPending: boolean = false; // 双击判断\n // 事件处理器\n private screenSpaceEventHandler: Cesium.ScreenSpaceEventHandler | null = null;\n // 回调函数\n private onDrawStartCallback: (() => void) | null = null;\n private onDrawEndCallback: ((entity: Cesium.Entity | null) => void) | null =\n null;\n private onEntityRemovedCallback: ((entity: Cesium.Entity) => void) | null =\n null;\n private offsetHeight: number = 2;\n\n /**\n * 构造函数\n * @param viewer Cesium Viewer 实例\n */\n constructor(viewer: Cesium.Viewer) {\n if (!viewer || !(viewer instanceof Cesium.Viewer)) {\n throw new Error(\"Invalid Cesium Viewer instance provided.\");\n }\n this.viewer = viewer;\n this.scene = viewer.scene;\n this.entities = viewer.entities;\n\n // 根据地图模式设置偏移高度\n this.updateOffsetHeight();\n \n // 监听场景模式变化\n this.scene.morphComplete.addEventListener(() => {\n this.updateOffsetHeight();\n });\n\n // 确保启用地形深度测试以获得正确的高度\n this.scene.globe.depthTestAgainstTerrain = true;\n }\n\n /**\n * 根据场景模式更新偏移高度\n */\n private updateOffsetHeight(): void {\n if (this.scene.mode === Cesium.SceneMode.SCENE3D) {\n this.offsetHeight = 100; // 3D模式使用100米偏移,所有元素都浮动\n } else {\n this.offsetHeight = 0; // 2D模式使用0米偏移,所有元素都贴近地面\n }\n }\n\n /**\n * 手动设置偏移高度\n * @param height 偏移高度(米)\n */\n public setOffsetHeight(height: number): void {\n this.offsetHeight = height;\n }\n\n /**\n * 获取当前偏移高度\n * @returns 当前偏移高度(米)\n */\n public getOffsetHeight(): number {\n return this.offsetHeight;\n }\n\n clearFrustum(): void {\n // 清理视锥体图元\n this.frustumPrimitives.forEach((primitive) => {\n if (primitive && !primitive.isDestroyed()) {\n this.viewer.scene.primitives.remove(primitive);\n }\n });\n this.frustumPrimitives = [];\n\n // 清理视锥体专用的事件处理器\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n // 视锥体功能\n drawFrustum(options: FrustumOptions = {}): void {\n try {\n this.clearFrustum();\n\n // 参数验证\n const fov = Math.max(1, Math.min(179, options.fov || 60)); // 限制FOV范围\n const aspectRatio = Math.max(0.1, options.aspectRatio || 1.0);\n const near = Math.max(0.1, options.near || 1.0);\n const far = Math.max(near + 1, options.far || 1000.0);\n\n const position = options.position || this.viewer.camera.positionWC;\n const orientation =\n options.orientation ||\n Cesium.Quaternion.fromRotationMatrix(\n Cesium.Matrix4.getRotation(\n this.viewer.camera.transform,\n new Cesium.Matrix3()\n )\n );\n\n const frustum = new Cesium.PerspectiveFrustum({\n fov: Cesium.Math.toRadians(fov),\n aspectRatio: aspectRatio,\n near: near,\n far: far,\n });\n\n // 创建视锥体填充\n const fillGeometry = new Cesium.FrustumGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n vertexFormat: Cesium.VertexFormat.POSITION_ONLY,\n });\n\n const fillInstance = new Cesium.GeometryInstance({\n geometry: fillGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.fillColor || new Cesium.Color(1.0, 0.0, 0.0, 0.3)\n ),\n },\n });\n\n const fillPrimitive = new Cesium.Primitive({\n geometryInstances: fillInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n // 创建视锥体轮廓\n const outlineGeometry = new Cesium.FrustumOutlineGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n });\n\n const outlineInstance = new Cesium.GeometryInstance({\n geometry: outlineGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.outlineColor || new Cesium.Color(1.0, 1.0, 1.0, 1.0)\n ),\n },\n });\n\n const outlinePrimitive = new Cesium.Primitive({\n geometryInstances: outlineInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n this.viewer.scene.primitives.add(fillPrimitive);\n this.viewer.scene.primitives.add(outlinePrimitive);\n this.frustumPrimitives.push(fillPrimitive, outlinePrimitive);\n\n // 右键点击事件\n if (options.onRightClick && this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.setInputAction((movement: any) => {\n if (movement.position && options.onRightClick) {\n options.onRightClick(position);\n }\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n }\n } catch (error) {\n console.error(\"绘制视锥体时发生错误:\", error);\n // 确保在出错时也清理资源\n this.clearFrustum();\n }\n }\n\n /**\n * 开始绘制线条\n */\n startDrawingLine(): void {\n this.startDrawing(\"line\");\n }\n\n /**\n * 开始绘制多边形(仅边线)\n */\n startDrawingPolygon(): void {\n this.startDrawing(\"polygon\");\n }\n\n /**\n * 开始绘制矩形\n */\n startDrawingRectangle(): void {\n this.startDrawing(\"rectangle\");\n }\n\n /**\n * 内部统一的开始绘制方法\n * @param mode 绘制模式\n */\n private startDrawing(mode: \"line\" | \"polygon\" | \"rectangle\"): void {\n this.endDrawingInternal(false); // 结束任何正在进行的绘制,但不清空已完成的实体\n\n this.drawMode = mode;\n this.isDrawing = true;\n this.tempPositions = [];\n this.tempEntities = [];\n\n this.activateDrawingHandlers();\n\n // 触发开始绘制回调\n if (this.onDrawStartCallback) {\n this.onDrawStartCallback();\n }\n }\n\n /**\n * 激活屏幕空间事件处理器\n */\n private activateDrawingHandlers(): void {\n this.deactivateDrawingHandlers(); // 确保之前的手柄已销毁\n\n this.screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(\n this.scene.canvas\n );\n\n // 左键点击添加点\n this.screenSpaceEventHandler.setInputAction(\n (click: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n if (!this.isDrawing) return;\n if (this._doubleClickPending) {\n this._doubleClickPending = false;\n return;\n }\n const cartesian = this.pickGlobePosition(click.position);\n if (cartesian) {\n this.addPoint(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.LEFT_CLICK\n );\n\n // 右键删除最后一个点\n this.screenSpaceEventHandler.setInputAction(() => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n this.removeLastPoint();\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n\n // 鼠标移动更新预览\n this.screenSpaceEventHandler.setInputAction(\n (move: Cesium.ScreenSpaceEventHandler.MotionEvent) => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n const cartesian = this.pickGlobePosition(move.endPosition);\n if (cartesian) {\n this.updatePreview(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.MOUSE_MOVE\n );\n\n // 双击结束绘制\n const mapDoubleClickAct =\n this.viewer.cesiumWidget.screenSpaceEventHandler.getInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.screenSpaceEventHandler.setInputAction(\n (dblClick: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n if (!this.isDrawing) return;\n this._doubleClickPending = true;\n this.finishDrawing();\n // 恢复 Cesium 默认的双击行为(如果存在的话)\n if (mapDoubleClickAct) {\n this.viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(\n mapDoubleClickAct,\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n }\n },\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n }\n\n /**\n * 拾取地形或椭球体上的位置\n * @param windowPosition 屏幕坐标\n * @returns 世界坐标 Cartesian3 或 null\n */\n private pickGlobePosition(\n windowPosition: Cesium.Cartesian2\n ): Cesium.Cartesian3 | null {\n // 首先尝试从地形拾取\n const ray = this.viewer.camera.getPickRay(windowPosition);\n if (ray) {\n const position = this.scene.globe.pick(ray, this.scene);\n if (Cesium.defined(position)) {\n return position;\n }\n }\n // 如果地形拾取失败,回退到椭球体拾取\n const ellipsoidPosition = this.viewer.camera.pickEllipsoid(\n windowPosition,\n this.scene.globe.ellipsoid\n );\n return ellipsoidPosition ?? null;\n }\n\n /**\n * 添加一个点到临时位置数组并创建点实体\n * @param position 世界坐标\n */\n private addPoint(position: Cesium.Cartesian3): void {\n this.tempPositions.push(position.clone());\n\n // 根据2D/3D模式设置点的高度\n const carto = Cesium.Cartographic.fromCartesian(position);\n const elevatedPosition = Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + (this.drawMode !== \"line\" ? 0 : this.offsetHeight)\n );\n\n const pointEntity = this.entities.add({\n position: elevatedPosition,\n point: {\n pixelSize: 8,\n color: Cesium.Color.RED,\n outlineColor: Cesium.Color.WHITE,\n outlineWidth: 3,\n heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,\n scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),\n },\n });\n this.tempEntities.push(pointEntity);\n this.updateDrawingEntity();\n }\n\n /**\n * 删除最后一个添加的点及其相关的临时实体\n */\n private removeLastPoint(): void {\n if (this.tempPositions.length > 0) {\n // 移除最后一个位置\n this.tempPositions.pop();\n\n // 移除所有临时实体(包括点实体和线/面实体)\n this.tempEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n\n // 移除所有临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempLabelEntities = [];\n\n // 重新创建剩余的点实体和绘制实体\n this.recreateRemainingEntities();\n }\n }\n\n /**\n * 重新创建剩余的点实体和绘制实体\n * 用于右键删除点后的重建\n */\n private recreateRemainingEntities(): void {\n // 重新创建所有剩余的点实体\n this.tempPositions.forEach((position) => {\n const carto = Cesium.Cartographic.fromCartesian(position);\n const elevatedPosition = Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n\n const pointEntity = this.entities.add({\n position: elevatedPosition,\n point: {\n pixelSize: 8,\n color: Cesium.Color.RED,\n outlineColor: Cesium.Color.WHITE,\n outlineWidth: 3,\n heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,\n scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),\n },\n });\n this.tempEntities.push(pointEntity);\n });\n\n // 重新创建绘制实体(线/面)\n this.updateDrawingEntity();\n }\n\n /**\n * 更新预览线/面\n * @param currentMousePosition 当前鼠标位置世界坐标\n */\n private updatePreview(currentMousePosition: Cesium.Cartesian3): void {\n this.updateDrawingEntity(currentMousePosition);\n }\n\n /**\n * 核心方法:根据当前点序列更新或创建临时的线/面实体\n * @param previewPoint 可选的预览点,用于显示动态效果\n */\n private updateDrawingEntity(previewPoint?: Cesium.Cartesian3): void {\n // 移除旧的活动实体(只移除线和面,保留点实体)\n const entitiesToRemove: Cesium.Entity[] = [];\n this.tempEntities.forEach((entity) => {\n if (entity && (entity.polyline || entity.polygon || entity.rectangle)) {\n entitiesToRemove.push(entity);\n }\n });\n \n // 移除线/面实体\n entitiesToRemove.forEach((entity) => {\n this.entities.remove(entity);\n const index = this.tempEntities.indexOf(entity);\n if (index > -1) {\n this.tempEntities.splice(index, 1);\n }\n });\n \n // 移除旧的临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempLabelEntities = [];\n const positions = [...this.tempPositions];\n if (previewPoint) {\n positions.push(previewPoint);\n }\n\n if (positions.length < 2) return;\n\n let activeEntity: Cesium.Entity | undefined;\n\n if (this.drawMode === \"line\") {\n // 根据2D/3D模式创建线条\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n activeEntity = this.entities.add({\n polyline: {\n positions: elevatedPositions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: false,\n },\n });\n } else {\n // 2D模式:贴近地面\n activeEntity = this.entities.add({\n polyline: {\n positions: positions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n }\n this.tempEntities.push(activeEntity);\n\n // 为每一段添加距离标签(只显示距离大于1米的标签)\n for (let i = 0; i < positions.length - 1; i++) {\n const startPos = positions[i];\n const endPos = positions[i + 1];\n const distance = Cesium.Cartesian3.distance(startPos, endPos);\n \n // 只显示距离大于5米的标签,避免显示过小的距离\n if (distance > 5.0) {\n const midPoint = Cesium.Cartesian3.midpoint(\n startPos,\n endPos,\n new Cesium.Cartesian3()\n );\n // 计算标签位置,避免重叠\n const labelOffset = i % 2 === 0 ? -25 : 25; // 交替显示在线的上方和下方\n const labelEntity = this.entities.add({\n position: midPoint,\n label: {\n text: `${distance.toFixed(2)} m`,\n font: \"16px Arial\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 3,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, labelOffset),\n heightReference: this.offsetHeight > 0 ? Cesium.HeightReference.RELATIVE_TO_GROUND : Cesium.HeightReference.CLAMP_TO_GROUND,\n scale: 1.0,\n showBackground: true,\n backgroundColor: Cesium.Color.BLACK.withAlpha(0.8),\n backgroundPadding: new Cesium.Cartesian2(6, 3),\n },\n });\n this.tempLabelEntities.push(labelEntity);\n }\n }\n\n // 添加总距离标签(在最后一个点)\n if (positions.length > 1) {\n let totalDistance = 0;\n for (let i = 1; i < positions.length; i++) {\n totalDistance += Cesium.Cartesian3.distance(\n positions[i - 1],\n positions[i]\n );\n }\n // 根据offsetHeight计算标签位置,与line的绘制方式保持一致\n let labelPosition = positions[positions.length - 1];\n if (this.offsetHeight > 0) {\n // 3D模式:抬高标签位置\n const carto = Cesium.Cartographic.fromCartesian(labelPosition);\n labelPosition = Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n }\n \n const totalLabelEntity = this.entities.add({\n position: labelPosition,\n label: {\n text: `总长: ${totalDistance.toFixed(2)} m`,\n font: \"18px Arial\",\n fillColor: Cesium.Color.YELLOW,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 3,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, 40),\n heightReference: this.offsetHeight > 0 ? Cesium.HeightReference.NONE : Cesium.HeightReference.CLAMP_TO_GROUND,\n scale: 1.0,\n showBackground: true,\n backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),\n backgroundPadding: new Cesium.Cartesian2(8, 4),\n },\n });\n this.tempLabelEntities.push(totalLabelEntity);\n }\n } else if (this.drawMode === \"polygon\") {\n // 根据2D/3D模式绘制多边形区域\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n activeEntity = this.entities.add({\n polygon: {\n hierarchy: new Cesium.CallbackProperty(() => {\n return new Cesium.PolygonHierarchy(elevatedPositions);\n }, false),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.NONE,\n },\n });\n } else {\n // 2D模式:贴近地面\n activeEntity = this.entities.add({\n polygon: {\n hierarchy: new Cesium.CallbackProperty(() => {\n return new Cesium.PolygonHierarchy(positions);\n }, false),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n if (this.offsetHeight > 0) {\n // 3D模式:使用挤压高度\n activeEntity = this.entities.add({\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.NONE,\n extrudedHeight: this.offsetHeight,\n },\n });\n } else {\n // 2D模式:贴近地面\n activeEntity = this.entities.add({\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n }\n\n if (activeEntity) {\n this.tempEntities.push(activeEntity);\n }\n }\n\n /**\n * 完成当前绘制操作\n */\n private finishDrawing(): void {\n if (this.tempPositions.length < (this.drawMode === \"rectangle\" ? 2 : 2)) {\n // 点数不足,取消绘制\n this.endDrawingInternal(true);\n return;\n }\n let finalEntity: Cesium.Entity | null = null;\n const positions = this.tempPositions.map((p) => p.clone());\n\n if (this.drawMode === \"line\") {\n // 根据2D/3D模式创建最终线条\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n finalEntity = this.entities.add({\n name: \"绘制的线\",\n polyline: {\n positions: elevatedPositions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: false,\n },\n });\n } else {\n // 2D模式:贴近地面\n finalEntity = this.entities.add({\n name: \"绘制的线\",\n polyline: {\n positions: positions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n }\n\n // 标签已经在 updateDrawingEntity 中创建,这里不需要重复创建\n } else if (this.drawMode === \"polygon\") {\n // 根据2D/3D模式绘制最终多边形区域\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n finalEntity = this.entities.add({\n name: \"绘制的多边形区域\",\n polygon: {\n hierarchy: new Cesium.PolygonHierarchy(elevatedPositions),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.NONE,\n },\n });\n } else {\n // 2D模式:贴近地面\n finalEntity = this.entities.add({\n name: \"绘制的多边形区域\",\n polygon: {\n hierarchy: new Cesium.PolygonHierarchy(positions),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n // 添加面积标签\n const area = this.calculatePolygonArea(positions);\n if (area > 0) {\n const center = this.calculatePolygonCenter(positions);\n const areaLabelEntity = this.entities.add({\n position: center,\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.finishedLabelEntities.push(areaLabelEntity);\n }\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n if (this.offsetHeight > 0) {\n // 3D模式:使用挤压高度\n finalEntity = this.entities.add({\n name: \"绘制的矩形\",\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.NONE,\n extrudedHeight: this.offsetHeight,\n },\n });\n } else {\n // 2D模式:贴近地面\n finalEntity = this.entities.add({\n name: \"绘制的矩形\",\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n // 添加面积标签\n const area = this.calculateRectangleArea(rect);\n if (area > 0) {\n const rectCenter = Cesium.Rectangle.center(rect);\n const rectAreaLabelEntity = this.entities.add({\n position: Cesium.Cartesian3.fromRadians(\n rectCenter.longitude,\n rectCenter.latitude\n ),\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.finishedLabelEntities.push(rectAreaLabelEntity);\n }\n }\n\n // 将完成的实体存入列表\n if (finalEntity) {\n this.finishedEntities.push(finalEntity);\n }\n\n // 将临时标签实体转移到已完成标签实体数组中\n this.tempLabelEntities.forEach((entity) => {\n this.finishedLabelEntities.push(entity);\n });\n this.tempLabelEntities = [];\n\n // 将临时点实体转移到已完成点实体数组中\n this.tempEntities.forEach((entity) => {\n if (entity && entity.point) {\n this.finishedPointEntities.push(entity);\n } else {\n // 非点实体直接移除\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n this.tempPositions = [];\n\n if (true) { // resetMode\n this.drawMode = null;\n this.isDrawing = false;\n this.deactivateDrawingHandlers();\n }\n\n // 触发结束绘制回调\n if (this.onDrawEndCallback) {\n this.onDrawEndCallback(finalEntity);\n }\n }\n\n /**\n * 内部方法:重置绘图状态和清理临时数据\n * @param resetMode 是否重置绘图模式和状态标志\n */\n private endDrawingInternal(resetMode: boolean): void {\n // 清理临时实体\n this.tempEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.tempEntities = [];\n this.tempPositions = [];\n // 清理临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.tempLabelEntities = [];\n\n if (resetMode) {\n this.drawMode = null;\n this.isDrawing = false;\n this.deactivateDrawingHandlers();\n }\n }\n\n /**\n * 公共方法:结束当前绘制(如果正在进行)\n */\n endDrawing(): void {\n if (this.isDrawing) {\n this.finishDrawing();\n } else {\n // 如果没有在绘制,也执行一次清理\n this.endDrawingInternal(true);\n }\n }\n\n /**\n * 销毁事件处理器\n */\n private deactivateDrawingHandlers(): void {\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n\n /**\n * 清除所有已绘制的实体\n */\n clearAll(): void {\n // 先结束可能的绘制\n this.endDrawing();\n \n // 强制清除所有点实体\n this.clearAllPoints();\n \n // 清除所有已完成的实体\n this.finishedEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.finishedEntities = [];\n \n // 清除所有已完成的标签实体\n this.finishedLabelEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.finishedLabelEntities = [];\n \n // 清除所有通过公共方法创建的实体\n this.publicEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.publicEntities = [];\n \n // 清理临时实体(包括绘制过程中的点实体)\n this.tempEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n \n // 清理临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n if (entity && entity.label) {\n this.entities.remove(entity);\n }\n });\n this.tempLabelEntities = [];\n \n // 确保清理所有可能残留的实体\n this.tempPositions = [];\n }\n\n /**\n * 清除所有实体(包括未跟踪的实体)\n * 这是一个更彻底的清理方法,会清除场景中的所有实体\n */\n clearAllEntities(): void {\n // 先结束可能的绘制\n this.endDrawing();\n // 清除场景中的所有实体\n this.entities.removeAll();\n // 重置所有跟踪数组\n this.finishedEntities = [];\n this.finishedLabelEntities = [];\n this.finishedPointEntities = [];\n this.publicEntities = [];\n this.tempEntities = [];\n this.tempLabelEntities = [];\n this.tempPositions = [];\n }\n\n /**\n * 强制清除所有点实体\n * 用于解决点实体无法删除的问题\n */\n clearAllPoints(): void {\n // 清除所有已完成的点实体\n this.finishedPointEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.finishedPointEntities = [];\n \n // 清除临时点实体\n this.tempEntities.forEach((entity) => {\n if (entity && entity.point) {\n this.entities.remove(entity);\n }\n });\n \n // 清除所有可能的点实体(通过实体名称查找)\n const allEntities = this.entities.values;\n for (let i = allEntities.length - 1; i >= 0; i--) {\n const entity = allEntities[i];\n if (entity && entity.point) {\n this.entities.remove(entity);\n }\n }\n }\n\n /**\n * 删除一个指定的已完成实体\n * @param entity 要删除的实体\n */\n removeEntity(entity: Cesium.Entity): void {\n const index = this.finishedEntities.indexOf(entity);\n if (index > -1) {\n this.entities.remove(entity);\n this.finishedEntities.splice(index, 1);\n if (this.onEntityRemovedCallback) {\n this.onEntityRemovedCallback(entity);\n }\n }\n }\n\n /**\n * 获取所有已完成的实体\n * @returns 实体数组\n */\n getFinishedEntities(): Cesium.Entity[] {\n return [...this.finishedEntities];\n }\n\n // --- 辅助计算函数 ---\n private calculateRectangle(\n p1: Cesium.Cartesian3,\n p2: Cesium.Cartesian3\n ): Cesium.Rectangle {\n const cartographic1 = Cesium.Cartographic.fromCartesian(p1);\n const cartographic2 = Cesium.Cartographic.fromCartesian(p2);\n const west = Math.min(cartographic1.longitude, cartographic2.longitude);\n const east = Math.max(cartographic1.longitude, cartographic2.longitude);\n const south = Math.min(cartographic1.latitude, cartographic2.latitude);\n const north = Math.max(cartographic1.latitude, cartographic2.latitude);\n return new Cesium.Rectangle(west, south, east, north);\n }\n\n private calculateRectangleArea(rect: Cesium.Rectangle): number {\n const west = rect.west;\n const south = rect.south;\n const east = rect.east;\n const north = rect.north;\n\n const width = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(east, south)\n );\n const height = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(west, north)\n );\n\n return (width * height) / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonArea(positions: Cesium.Cartesian3[]): number {\n if (positions.length < 3) return 0;\n const ellipsoid = this.scene.globe.ellipsoid;\n let area = 0;\n const len = positions.length;\n for (let i = 0; i < len; i++) {\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\n area +=\n (p2.longitude - p1.longitude) *\n (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\n }\n area = Math.abs((area * 6378137.0 * 6378137.0) / 2.0); // WGS84半径\n return area / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonCenter(\n positions: Cesium.Cartesian3[]\n ): Cesium.Cartesian3 {\n if (positions.length === 0) return Cesium.Cartesian3.ZERO;\n let x = 0,\n y = 0,\n z = 0;\n for (let i = 0; i < positions.length; i++) {\n x += positions[i].x;\n y += positions[i].y;\n z += positions[i].z;\n }\n return new Cesium.Cartesian3(\n x / positions.length,\n y / positions.length,\n z / positions.length\n );\n }\n\n // --- 回调注册 ---\n\n /**\n * 设置开始绘制时的回调函数\n * @param callback 回调函数\n */\n onDrawStart(callback: () => void): void {\n this.onDrawStartCallback = callback;\n }\n\n /**\n * 设置结束绘制时的回调函数\n * @param callback 回调函数,参数为完成的实体或null\n */\n onDrawEnd(callback: (entity: Cesium.Entity | null) => void): void {\n this.onDrawEndCallback = callback;\n }\n\n /**\n * 设置实体被移除时的回调函数\n * @param callback 回调函数,参数为被移除的实体\n */\n onEntityRemoved(callback: (entity: Cesium.Entity) => void): void {\n this.onEntityRemovedCallback = callback;\n }\n\n /**\n * 绘制监控圆形区域\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param radius 监控范围半径(米)\n * @param options 可选配置\n */\n public drawMonitoringCircle(\n longitude: number,\n latitude: number,\n height: number,\n radius: number,\n options?: {\n borderColor?: string;\n fillColor?: string;\n borderWidth?: number;\n name?: string;\n }\n ): Cesium.Entity {\n const borderColor = options?.borderColor || \"#0062FF\";\n const fillColor = options?.fillColor || \"#0062FF\";\n const borderWidth = options?.borderWidth || 2;\n const name = options?.name || \"监控区域\";\n\n // 创建圆形区域\n const entity = this.entities.add({\n name: name,\n position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),\n ellipse: {\n semiMajorAxis: radius,\n semiMinorAxis: radius,\n material: Cesium.Color.fromCssColorString(fillColor).withAlpha(0.27),\n outline: true,\n outlineColor: Cesium.Color.fromCssColorString(borderColor),\n outlineWidth: borderWidth,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n\n // 将实体添加到跟踪数组中\n this.publicEntities.push(entity);\n\n return entity;\n }\n\n /**\n * 绘制垂直线条\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param options 可选配置\n */\n public drawVerticalLine(\n longitude: number,\n latitude: number,\n height: number,\n options?: {\n color?: string;\n width?: number;\n dashPattern?: number;\n name?: string;\n groundHeight?: number;\n }\n ): Cesium.Entity {\n const color = options?.color || \"#0062FF\";\n const width = options?.width || 2;\n const dashPattern = options?.dashPattern || 0x00ff00ff;\n const name = options?.name || \"垂直线条\";\n const groundHeight = options?.groundHeight || 0;\n\n // 计算地面位置\n const groundPosition = Cesium.Cartesian3.fromDegrees(\n longitude,\n latitude,\n groundHeight\n );\n const topPosition = Cesium.Cartesian3.fromDegrees(\n longitude,\n latitude,\n height\n );\n\n // 创建垂直线条\n const entity = this.entities.add({\n name: name,\n polyline: {\n positions: [groundPosition, topPosition],\n width: width,\n material: new Cesium.PolylineDashMaterialProperty({\n color: Cesium.Color.fromCssColorString(color),\n }),\n clampToGround: false,\n },\n });\n\n // 将实体添加到跟踪数组中\n this.publicEntities.push(entity);\n\n return entity;\n }\n\n /**\n * 销毁工具,清理所有事件监听器\n */\n destroy(): void {\n this.deactivateDrawingHandlers();\n this.clearFrustum(); // 清理视锥体相关资源\n // 可以选择不清除实体,由用户决定\n // this.clearAll();\n }\n}\n\n// 为了在 HTML 中通过 <script type=\"module\"> 或打包工具使用\n// @ts-ignore\nwindow.DrawHelper = DrawHelper;\n\nexport default DrawHelper;\n","import * as Cesium from 'cesium';\r\nimport type { Viewer, Cartesian3, Cartographic } from 'cesium';\r\nimport DrawHelper from './CesiumMapHelper';\r\n\r\n// 工具栏配置接口\r\nexport interface ToolbarConfig {\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\r\n buttonSize?: number;\r\n buttonSpacing?: number;\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderRadius?: number;\r\n borderWidth?: number;\r\n boxShadow?: string;\r\n zIndex?: number;\r\n buttons?: CustomButtonConfig[];\r\n}\r\n\r\n// 按钮配置接口\r\nexport interface ButtonConfig {\r\n id: string;\r\n icon: string;\r\n title: string;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n}\r\n\r\n// 自定义按钮配置接口\r\nexport interface CustomButtonConfig {\r\n id: string;\r\n icon: string | HTMLElement;\r\n title: string;\r\n enabled?: boolean;\r\n visible?: boolean;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n onClick?: (buttonId: string, buttonElement: HTMLElement) => void;\r\n}\r\n\r\n// 搜索回调接口\r\nexport interface SearchCallback {\r\n onSearch?: (query: string) => Promise<SearchResult[]>;\r\n onSelect?: (result: SearchResult) => void;\r\n onSearchInput?: (query: string, container: HTMLElement) => void;\r\n onSearchResults?: (results: SearchResult[], container: HTMLElement) => void;\r\n}\r\n\r\n// 搜索结果接口\r\nexport interface SearchResult {\r\n name: string;\r\n address: string;\r\n longitude: number;\r\n latitude: number;\r\n height?: number;\r\n}\r\n\r\n// 测量回调接口\r\nexport interface MeasurementCallback {\r\n onDistanceComplete?: (positions: Cartesian3[], distance: number) => void;\r\n onAreaComplete?: (positions: Cartesian3[], area: number) => void;\r\n onClear?: () => void;\r\n}\r\n\r\n// 缩放回调接口\r\nexport interface ZoomCallback {\r\n onZoomIn?: (beforeLevel: number, afterLevel: number) => void;\r\n onZoomOut?: (beforeLevel: number, afterLevel: number) => void;\r\n}\r\n\r\n// 地图类型接口\r\nexport interface MapType {\r\n id: string;\r\n name: string;\r\n thumbnail: string;\r\n provider: Cesium.ImageryProvider;\r\n}\r\n\r\n/**\r\n * Cesium地图工具栏类\r\n * 提供搜索、测量、2D/3D切换、图层切换、定位、缩放、全屏等功能\r\n */\r\nexport class CesiumMapToolbar {\r\n private viewer: Viewer;\r\n private drawHelper: DrawHelper;\r\n private container: HTMLElement;\r\n private toolbarElement!: HTMLElement;\r\n private config: ToolbarConfig;\r\n private searchCallback?: SearchCallback;\r\n private measurementCallback?: MeasurementCallback;\r\n private zoomCallback?: ZoomCallback;\r\n private initialCenter?: { longitude: number; latitude: number; height: number };\r\n private isFullscreen: boolean = false;\r\n private currentMapType: string = 'imagery';\r\n\r\n // 地图类型配置\r\n private mapTypes: MapType[] = [\r\n {\r\n id: 'normal',\r\n name: '天地图-普通',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: '3d',\r\n name: '天地图-三维',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'imagery',\r\n name: '天地图-影像',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'terrain',\r\n name: '天地图-地形',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n }\r\n ];\r\n\r\n constructor(\r\n viewer: Viewer,\r\n container: HTMLElement,\r\n config: ToolbarConfig = {},\r\n callbacks?: {\r\n search?: SearchCallback;\r\n measurement?: MeasurementCallback;\r\n zoom?: ZoomCallback;\r\n },\r\n initialCenter?: { longitude: number; latitude: number; height: number }\r\n ) {\r\n this.viewer = viewer;\r\n this.container = container;\r\n this.config = {\r\n position: 'bottom-right',\r\n buttonSize: 40,\r\n buttonSpacing: 8,\r\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\r\n borderColor: '#e0e0e0',\r\n borderRadius: 6,\r\n boxShadow: '0 2px 10px rgba(0, 0, 0, 0.1)',\r\n zIndex: 1000,\r\n ...config\r\n };\r\n this.searchCallback = callbacks?.search;\r\n this.measurementCallback = callbacks?.measurement;\r\n this.zoomCallback = callbacks?.zoom;\r\n\r\n // 设置初始中心点\r\n this.initialCenter = initialCenter;\r\n\r\n // 初始化绘图助手\r\n this.drawHelper = new DrawHelper(viewer);\r\n this.setupDrawHelperCallbacks();\r\n\r\n // 创建工具栏\r\n this.createToolbar();\r\n }\r\n\r\n /**\r\n * 设置初始中心点\r\n */\r\n public setInitialCenter(center: { longitude: number; latitude: number; height: number }): void {\r\n this.initialCenter = center;\r\n }\r\n\r\n /**\r\n * 获取初始中心点\r\n */\r\n public getInitialCenter(): { longitude: number; latitude: number; height: number } | undefined {\r\n return this.initialCenter;\r\n }\r\n\r\n /**\r\n * 复位到初始位置(公共方法)\r\n */\r\n public resetToInitialLocation(): void {\r\n this.resetLocation();\r\n }\r\n\r\n /**\r\n * 更新按钮配置\r\n */\r\n public updateButtonConfig(buttonId: string, config: Partial<CustomButtonConfig>): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (!button) return;\r\n\r\n // 更新按钮属性\r\n if (config.title) button.title = config.title;\r\n if (config.icon) this.setButtonIcon(button, config.icon);\r\n if (config.size) {\r\n button.style.width = `${config.size}px`;\r\n button.style.height = `${config.size}px`;\r\n }\r\n if (config.color) button.style.background = config.color;\r\n }\r\n\r\n /**\r\n * 添加自定义按钮\r\n */\r\n public addCustomButton(config: CustomButtonConfig): void {\r\n const buttonConfig: ButtonConfig = {\r\n id: config.id,\r\n icon: typeof config.icon === 'string' ? config.icon : '',\r\n title: config.title,\r\n size: config.size,\r\n color: config.color,\r\n hoverColor: config.hoverColor,\r\n activeColor: config.activeColor\r\n };\r\n\r\n const buttonElement = this.createButton(buttonConfig);\r\n this.toolbarElement.appendChild(buttonElement);\r\n\r\n // 更新配置\r\n if (!this.config.buttons) {\r\n this.config.buttons = [];\r\n }\r\n this.config.buttons.push(config);\r\n }\r\n\r\n /**\r\n * 移除按钮\r\n */\r\n public removeButton(buttonId: string): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (button && button.parentNode) {\r\n button.parentNode.removeChild(button);\r\n }\r\n\r\n // 从配置中移除\r\n if (this.config.buttons) {\r\n this.config.buttons = this.config.buttons.filter(btn => btn.id !== buttonId);\r\n }\r\n }\r\n\r\n /**\r\n * 获取按钮元素\r\n */\r\n public getButtonElement(buttonId: string): HTMLElement | null {\r\n return this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n }\r\n\r\n /**\r\n * 设置绘图助手回调\r\n */\r\n private setupDrawHelperCallbacks(): void {\r\n this.drawHelper.onDrawStart(() => {\r\n console.log('开始绘制');\r\n });\r\n\r\n this.drawHelper.onDrawEnd((entity) => {\r\n if (entity) {\r\n console.log('绘制完成', entity);\r\n // 根据绘制类型触发相应回调\r\n if (entity.polyline) {\r\n // 测距完成\r\n const positions = entity.polyline.positions?.getValue(Cesium.JulianDate.now()) as Cartesian3[];\r\n if (positions && this.measurementCallback?.onDistanceComplete) {\r\n let totalDistance = 0;\r\n for (let i = 1; i < positions.length; i++) {\r\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\r\n }\r\n this.measurementCallback.onDistanceComplete(positions, totalDistance);\r\n }\r\n } else if (entity.polygon) {\r\n // 测面积完成\r\n const positions = entity.polygon.hierarchy?.getValue(Cesium.JulianDate.now()) as Cesium.PolygonHierarchy;\r\n if (positions && this.measurementCallback?.onAreaComplete) {\r\n // 计算面积\r\n const area = this.calculatePolygonArea(positions.positions);\r\n this.measurementCallback.onAreaComplete(positions.positions, area);\r\n }\r\n }\r\n }\r\n });\r\n\r\n this.drawHelper.onEntityRemoved((entity) => {\r\n console.log('实体被移除', entity);\r\n });\r\n }\r\n\r\n /**\r\n * 计算多边形面积\r\n */\r\n private calculatePolygonArea(positions: Cartesian3[]): number {\r\n if (positions.length < 3) return 0;\r\n \r\n const ellipsoid = this.viewer.scene.globe.ellipsoid;\r\n let area = 0;\r\n const len = positions.length;\r\n \r\n for (let i = 0; i < len; i++) {\r\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\r\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\r\n area += (p2.longitude - p1.longitude) * (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\r\n }\r\n \r\n area = Math.abs(area * 6378137.0 * 6378137.0 / 2.0);\r\n return area / 1e6; // 转换为平方公里\r\n }\r\n\r\n /**\r\n * 创建工具栏\r\n */\r\n private createToolbar(): void {\r\n this.toolbarElement = document.createElement('div');\r\n this.toolbarElement.className = 'cesium-map-toolbar';\r\n this.toolbarElement.style.cssText = `\r\n position: absolute;\r\n ${this.config.position?.includes('right') ? 'right' : 'left'}: 10px;\r\n ${this.config.position?.includes('bottom') ? 'bottom' : 'top'}: 10px;\r\n background: ${this.config.backgroundColor};\r\n border: ${this.config.borderWidth}px solid ${this.config.borderColor};\r\n border-radius: ${this.config.borderRadius}px;\r\n box-shadow: ${this.config.boxShadow};\r\n padding: 8px;\r\n z-index: ${this.config.zIndex};\r\n display: flex;\r\n flex-direction: column;\r\n gap: ${this.config.buttonSpacing}px;\r\n `;\r\n\r\n // 获取按钮配置\r\n const buttons = this.getButtonConfigs();\r\n\r\n buttons.forEach(button => {\r\n const buttonElement = this.createButton(button);\r\n this.toolbarElement.appendChild(buttonElement);\r\n });\r\n\r\n this.container.appendChild(this.toolbarElement);\r\n }\r\n\r\n /**\r\n * 获取按钮配置\r\n */\r\n private getButtonConfigs(): ButtonConfig[] {\r\n // 默认按钮配置\r\n const defaultButtons: ButtonConfig[] = [\r\n { id: 'search', icon: '🔍', title: '搜索' },\r\n { id: 'measure', icon: '📏', title: '测量' },\r\n { id: 'view2d3d', icon: '2D', title: '2D或3D' },\r\n { id: 'layers', icon: '📚', title: '图层切换' },\r\n { id: 'location', icon: '🎯', title: '定位' },\r\n { id: 'zoom-in', icon: '🔍+', title: '放大' },\r\n { id: 'zoom-out', icon: '🔍-', title: '缩小' },\r\n { id: 'fullscreen', icon: '⛶', title: '全屏' }\r\n ];\r\n\r\n // 如果用户提供了自定义按钮配置,则使用自定义配置\r\n if (this.config.buttons && this.config.buttons.length > 0) {\r\n return this.config.buttons.map(customButton => ({\r\n id: customButton.id,\r\n icon: typeof customButton.icon === 'string' ? customButton.icon : '',\r\n title: customButton.title,\r\n size: customButton.size,\r\n color: customButton.color,\r\n hoverColor: customButton.hoverColor,\r\n activeColor: customButton.activeColor\r\n }));\r\n }\r\n\r\n return defaultButtons;\r\n }\r\n\r\n /**\r\n * 创建按钮\r\n */\r\n private createButton(config: ButtonConfig): HTMLElement {\r\n const button = document.createElement('div');\r\n button.className = 'cesium-toolbar-button';\r\n button.setAttribute('data-tool', config.id);\r\n button.title = config.title;\r\n \r\n const buttonSize = config.size || this.config.buttonSize;\r\n const buttonColor = config.color || 'rgba(66, 133, 244, 0.4)';\r\n const buttonHoverColor = config.hoverColor || 'rgba(51, 103, 214, 0.9)';\r\n \r\n button.style.cssText = `\r\n width: ${buttonSize}px;\r\n height: ${buttonSize}px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: ${buttonColor};\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n font-weight: bold;\r\n transition: all 0.2s ease;\r\n user-select: none;\r\n position: relative;\r\n `;\r\n\r\n // 设置图标内容\r\n this.setButtonIcon(button, config.icon);\r\n\r\n // 悬停效果\r\n button.addEventListener('mouseenter', () => {\r\n button.style.background = buttonHoverColor;\r\n button.style.transform = 'scale(1.05)';\r\n });\r\n\r\n button.addEventListener('mouseleave', () => {\r\n button.style.background = buttonColor;\r\n button.style.transform = 'scale(1)';\r\n });\r\n\r\n // 处理点击事件\r\n this.setupButtonEvents(button, config);\r\n\r\n return button;\r\n }\r\n\r\n /**\r\n * 设置按钮图标\r\n */\r\n private setButtonIcon(button: HTMLElement, icon: string | HTMLElement): void {\r\n if (typeof icon === 'string') {\r\n button.innerHTML = icon;\r\n } else if (icon instanceof HTMLElement) {\r\n button.innerHTML = '';\r\n button.appendChild(icon);\r\n }\r\n }\r\n\r\n /**\r\n * 设置按钮事件\r\n */\r\n private setupButtonEvents(button: HTMLElement, config: ButtonConfig): void {\r\n // 查找自定义按钮配置\r\n const customButton = this.config.buttons?.find(btn => btn.id === config.id);\r\n \r\n if (customButton?.onClick) {\r\n // 自定义按钮点击事件\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n customButton.onClick!(config.id, button);\r\n });\r\n } else if (!['search', 'measure', 'layers'].includes(config.id)) {\r\n // 默认按钮点击事件(除了搜索、测量、图层切换按钮)\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.handleButtonClick(config.id, button);\r\n });\r\n } else if (config.id === 'search') {\r\n // 搜索按钮使用点击事件\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.handleButtonClick(config.id, button);\r\n });\r\n } else {\r\n // 测量、图层切换按钮使用hover事件\r\n button.addEventListener('mouseenter', () => {\r\n this.handleButtonClick(config.id, button);\r\n });\r\n \r\n // 添加鼠标离开事件来关闭菜单\r\n button.addEventListener('mouseleave', () => {\r\n this.closeMenuOnButtonLeave(config.id);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 按钮鼠标离开时关闭菜单\r\n */\r\n private closeMenuOnButtonLeave(buttonId: string): void {\r\n // 延迟关闭,给用户时间移动到菜单上\r\n setTimeout(() => {\r\n switch (buttonId) {\r\n case 'measure':\r\n const measureMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (measureMenu && !measureMenu.matches(':hover')) {\r\n measureMenu.remove();\r\n }\r\n break;\r\n case 'layers':\r\n const layersMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (layersMenu && !layersMenu.matches(':hover')) {\r\n layersMenu.remove();\r\n }\r\n break;\r\n }\r\n }, 100); // 100ms延迟,给用户时间移动到菜单\r\n }\r\n\r\n /**\r\n * 处理按钮点击\r\n */\r\n private handleButtonClick(buttonId: string, buttonElement: HTMLElement): void {\r\n switch (buttonId) {\r\n case 'search':\r\n this.toggleSearch(buttonElement);\r\n break;\r\n case 'measure':\r\n this.toggleMeasurement(buttonElement);\r\n break;\r\n case 'view2d3d':\r\n this.toggle2D3D(buttonElement);\r\n break;\r\n case 'layers':\r\n this.toggleLayers(buttonElement);\r\n break;\r\n case 'location':\r\n this.resetLocation();\r\n break;\r\n case 'zoom-in':\r\n this.zoomIn();\r\n break;\r\n case 'zoom-out':\r\n this.zoomOut();\r\n break;\r\n case 'fullscreen':\r\n this.toggleFullscreen();\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换搜索功能\r\n */\r\n private toggleSearch(buttonElement: HTMLElement): void {\r\n const existingSearch = this.toolbarElement.querySelector('.search-container');\r\n if (existingSearch) {\r\n // 如果搜索框已存在,关闭它\r\n existingSearch.remove();\r\n return;\r\n }\r\n\r\n const searchContainer = document.createElement('div');\r\n searchContainer.className = 'search-container';\r\n searchContainer.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 8px;\r\n min-width: 200px;\r\n z-index: 1001;\r\n `;\r\n\r\n const searchInput = document.createElement('input');\r\n searchInput.type = 'text';\r\n searchInput.placeholder = '请输入地址';\r\n searchInput.style.cssText = `\r\n padding: 6px 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n outline: none;\r\n `;\r\n\r\n const resultsContainer = document.createElement('div');\r\n resultsContainer.className = 'search-results';\r\n resultsContainer.style.cssText = `\r\n margin-top: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n `;\r\n\r\n searchContainer.appendChild(searchInput);\r\n searchContainer.appendChild(resultsContainer);\r\n\r\n // 插入到按钮前面\r\n this.toolbarElement.insertBefore(searchContainer, buttonElement);\r\n\r\n // 搜索功能\r\n let searchTimeout: ReturnType<typeof setTimeout>;\r\n searchInput.addEventListener('input', () => {\r\n clearTimeout(searchTimeout);\r\n const query = searchInput.value.trim();\r\n \r\n // 如果用户提供了自定义搜索输入处理逻辑\r\n if (this.searchCallback?.onSearchInput) {\r\n this.searchCallback.onSearchInput(query, resultsContainer);\r\n return;\r\n }\r\n \r\n if (query.length < 2) {\r\n resultsContainer.innerHTML = '';\r\n return;\r\n }\r\n\r\n searchTimeout = setTimeout(async () => {\r\n if (this.searchCallback?.onSearch) {\r\n try {\r\n const results = await this.searchCallback.onSearch(query);\r\n this.displaySearchResults(results, resultsContainer);\r\n } catch (error) {\r\n console.error('搜索失败:', error);\r\n resultsContainer.innerHTML = '<div style=\"padding: 8px; color: #666;\">搜索失败</div>';\r\n }\r\n } else {\r\n // 默认搜索逻辑\r\n this.performDefaultSearch(query, resultsContainer);\r\n }\r\n }, 300);\r\n });\r\n\r\n // 添加点击外部区域关闭搜索框的逻辑\r\n const closeSearchOnClickOutside = (event: MouseEvent) => {\r\n if (!searchContainer.contains(event.target as Node) && \r\n !buttonElement.contains(event.target as Node)) {\r\n searchContainer.remove();\r\n document.removeEventListener('click', closeSearchOnClickOutside);\r\n document.removeEventListener('keydown', closeSearchOnEscape);\r\n }\r\n };\r\n\r\n // 添加ESC键关闭搜索框的逻辑\r\n const closeSearchOnEscape = (event: KeyboardEvent) => {\r\n if (event.key === 'Escape') {\r\n searchContainer.remove();\r\n document.removeEventListener('click', closeSearchOnClickOutside);\r\n document.removeEventListener('keydown', closeSearchOnEscape);\r\n }\r\n };\r\n\r\n // 延迟添加事件监听器,避免立即触发\r\n setTimeout(() => {\r\n document.addEventListener('click', closeSearchOnClickOutside);\r\n document.addEventListener('keydown', closeSearchOnEscape);\r\n // 自动聚焦到搜索输入框\r\n searchInput.focus();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * 显示搜索结果\r\n */\r\n private displaySearchResults(results: SearchResult[], container: HTMLElement): void {\r\n // 如果用户提供了自定义搜索结果处理逻辑\r\n if (this.searchCallback?.onSearchResults) {\r\n this.searchCallback.onSearchResults(results, container);\r\n return;\r\n }\r\n\r\n // 默认搜索结果显示逻辑\r\n container.innerHTML = '';\r\n \r\n if (results.length === 0) {\r\n container.innerHTML = '<div style=\"padding: 8px; color: #666;\">未找到相关地址</div>';\r\n return;\r\n }\r\n\r\n results.forEach(result => {\r\n const resultItem = document.createElement('div');\r\n resultItem.style.cssText = `\r\n padding: 8px;\r\n border-bottom: 1px solid #f0f0f0;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n resultItem.innerHTML = `\r\n <div style=\"font-weight: bold; margin-bottom: 2px;\">${result.name}</div>\r\n <div style=\"font-size: 12px; color: #666;\">${result.address}</div>\r\n `;\r\n\r\n resultItem.addEventListener('mouseenter', () => {\r\n resultItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n resultItem.addEventListener('mouseleave', () => {\r\n resultItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n resultItem.addEventListener('click', () => {\r\n this.selectSearchResult(result);\r\n container.parentElement?.remove();\r\n });\r\n\r\n container.appendChild(resultItem);\r\n });\r\n }\r\n\r\n /**\r\n * 选择搜索结果\r\n */\r\n private selectSearchResult(result: SearchResult): void {\r\n // 飞行到指定位置\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n result.longitude,\r\n result.latitude,\r\n result.height || 1000\r\n ),\r\n duration: 1.0\r\n });\r\n\r\n // 触发回调\r\n if (this.searchCallback?.onSelect) {\r\n this.searchCallback.onSelect(result);\r\n }\r\n }\r\n\r\n /**\r\n * 默认搜索逻辑\r\n */\r\n private performDefaultSearch(query: string, container: HTMLElement): void {\r\n // 模拟搜索结果\r\n const mockResults: SearchResult[] = [\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n }\r\n ];\r\n\r\n this.displaySearchResults(mockResults, container);\r\n }\r\n\r\n /**\r\n * 切换测量功能\r\n */\r\n private toggleMeasurement(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'measurement-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 4px 0;\r\n min-width: 120px;\r\n z-index: 1001;\r\n `;\r\n\r\n const menuItems = [\r\n { id: 'measure-area', text: '测面积', icon: '📐' },\r\n { id: 'measure-distance', text: '测距', icon: '📏' },\r\n { id: 'clear-measurement', text: '清除', icon: '🗑️' }\r\n ];\r\n\r\n menuItems.forEach(item => {\r\n const menuItem = document.createElement('div');\r\n menuItem.style.cssText = `\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n menuItem.innerHTML = `${item.icon} ${item.text}`;\r\n\r\n menuItem.addEventListener('mouseenter', () => {\r\n menuItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n menuItem.addEventListener('mouseleave', () => {\r\n menuItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n menuItem.addEventListener('click', () => {\r\n this.handleMeasurementAction(item.id);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(menuItem);\r\n });\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 处理测量操作\r\n */\r\n private handleMeasurementAction(action: string): void {\r\n switch (action) {\r\n case 'measure-area':\r\n this.drawHelper.startDrawingPolygon();\r\n break;\r\n case 'measure-distance':\r\n this.drawHelper.startDrawingLine();\r\n break;\r\n case 'clear-measurement':\r\n this.drawHelper.clearAll();\r\n if (this.measurementCallback?.onClear) {\r\n this.measurementCallback.onClear();\r\n }\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换2D/3D视图\r\n */\r\n private toggle2D3D(buttonElement: HTMLElement): void {\r\n const currentMode = this.viewer.scene.mode;\r\n const targetMode = currentMode === Cesium.SceneMode.SCENE3D \r\n ? Cesium.SceneMode.SCENE2D \r\n : Cesium.SceneMode.SCENE3D;\r\n \r\n this.viewer.scene.mode = targetMode;\r\n \r\n // 更新按钮文本\r\n buttonElement.innerHTML = targetMode === Cesium.SceneMode.SCENE3D ? '3D' : '2D';\r\n }\r\n\r\n /**\r\n * 切换图层\r\n */\r\n private toggleLayers(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'layers-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 6px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n padding: 12px;\r\n min-width: 220px;\r\n max-width: 280px;\r\n z-index: 1001;\r\n display: flex;\r\n flex-direction: column;\r\n `;\r\n\r\n // 地图类型选择\r\n const mapTypeSection = document.createElement('div');\r\n mapTypeSection.style.cssText = `\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n `;\r\n mapTypeSection.innerHTML = '<div style=\"font-weight: bold; margin-bottom: 8px; color: #333; font-size: 14px;\">地图类型</div>';\r\n \r\n this.mapTypes.forEach(mapType => {\r\n const mapTypeItem = document.createElement('div');\r\n mapTypeItem.style.cssText = `\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n width: 100%;\r\n box-sizing: border-box;\r\n ${mapType.id === this.currentMapType ? 'background-color: #e3f2fd;' : ''}\r\n `;\r\n\r\n const thumbnail = document.createElement('img');\r\n thumbnail.src = mapType.thumbnail;\r\n thumbnail.style.cssText = `\r\n width: 24px; \r\n height: 24px; \r\n border-radius: 3px;\r\n flex-shrink: 0;\r\n `;\r\n\r\n const label = document.createElement('span');\r\n label.textContent = mapType.name;\r\n label.style.cssText = `\r\n font-size: 14px;\r\n color: #333;\r\n flex: 1;\r\n `;\r\n\r\n const checkmark = document.createElement('span');\r\n if (mapType.id === this.currentMapType) {\r\n checkmark.textContent = '✓';\r\n checkmark.style.cssText = `\r\n color: #1976d2; \r\n font-weight: bold; \r\n font-size: 16px;\r\n flex-shrink: 0;\r\n `;\r\n }\r\n\r\n mapTypeItem.appendChild(thumbnail);\r\n mapTypeItem.appendChild(label);\r\n mapTypeItem.appendChild(checkmark);\r\n\r\n mapTypeItem.addEventListener('mouseenter', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = '#f5f5f5';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('mouseleave', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = 'transparent';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('click', () => {\r\n this.switchMapType(mapType.id);\r\n menu.remove();\r\n });\r\n\r\n mapTypeSection.appendChild(mapTypeItem);\r\n });\r\n\r\n menu.appendChild(mapTypeSection);\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 切换地图类型\r\n */\r\n private switchMapType(mapTypeId: string): void {\r\n const mapType = this.mapTypes.find(mt => mt.id === mapTypeId);\r\n if (!mapType) return;\r\n\r\n // 移除当前图层\r\n this.viewer.imageryLayers.removeAll();\r\n \r\n // 添加新图层\r\n this.viewer.imageryLayers.addImageryProvider(mapType.provider);\r\n \r\n this.currentMapType = mapTypeId;\r\n }\r\n\r\n /**\r\n * 复位到初始位置\r\n */\r\n private resetLocation(): void {\r\n if (!this.initialCenter) {\r\n console.warn('未设置初始中心点,无法执行复位操作');\r\n return;\r\n }\r\n\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n this.initialCenter.longitude,\r\n this.initialCenter.latitude,\r\n this.initialCenter.height\r\n ),\r\n duration: 1.0\r\n });\r\n }\r\n\r\n /**\r\n * 放大\r\n */\r\n private zoomIn(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomIn(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomIn) {\r\n this.zoomCallback.onZoomIn(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 缩小\r\n */\r\n private zoomOut(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomOut(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomOut) {\r\n this.zoomCallback.onZoomOut(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 切换全屏\r\n */\r\n private toggleFullscreen(): void {\r\n if (!this.isFullscreen) {\r\n this.enterFullscreen();\r\n } else {\r\n this.exitFullscreen();\r\n }\r\n }\r\n\r\n /**\r\n * 进入全屏\r\n */\r\n private enterFullscreen(): void {\r\n const container = this.viewer.container;\r\n \r\n if (container.requestFullscreen) {\r\n container.requestFullscreen();\r\n } else if ((container as any).webkitRequestFullscreen) {\r\n (container as any).webkitRequestFullscreen();\r\n } else if ((container as any).msRequestFullscreen) {\r\n (container as any).msRequestFullscreen();\r\n }\r\n\r\n this.isFullscreen = true;\r\n \r\n // 监听全屏状态变化\r\n const fullscreenChange = () => {\r\n if (!document.fullscreenElement && \r\n !(document as any).webkitFullscreenElement && \r\n !(document as any).msFullscreenElement) {\r\n this.isFullscreen = false;\r\n document.removeEventListener('fullscreenchange', fullscreenChange);\r\n document.removeEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.removeEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n };\r\n\r\n document.addEventListener('fullscreenchange', fullscreenChange);\r\n document.addEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.addEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n\r\n /**\r\n * 退出全屏\r\n */\r\n private exitFullscreen(): void {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if ((document as any).webkitExitFullscreen) {\r\n (document as any).webkitExitFullscreen();\r\n } else if ((document as any).msExitFullscreen) {\r\n (document as any).msExitFullscreen();\r\n }\r\n\r\n this.isFullscreen = false;\r\n }\r\n\r\n /**\r\n * 销毁工具栏\r\n */\r\n destroy(): void {\r\n if (this.toolbarElement && this.toolbarElement.parentNode) {\r\n this.toolbarElement.parentNode.removeChild(this.toolbarElement);\r\n }\r\n this.drawHelper.destroy();\r\n }\r\n}\r\n","import * as Cesium from 'cesium'\nimport { Ion, Viewer, createWorldTerrainAsync, Terrain, Cartesian3, SampledPositionProperty, TerrainProvider } from 'cesium'\nimport type { Entity, Viewer as CesiumViewer, EntityCollection } from 'cesium'\n\n\ninterface InitOptions {\n terrain: Terrain, // 地形\n terrainProvider?: TerrainProvider // 地形提供者\n mapType?: string // 地图类型,默认为天地图\n imageryProvider?: Cesium.UrlTemplateImageryProvider // 自定义影像图层提供r\n imageryLayers?: Cesium.ImageryLayerCollection // 自定义影像图层集合\n terrainShadows?: Cesium.ShadowMode // 地形阴影\n contextOptions?: Cesium.ContextOptions // 上下文选项\n scene3DOnly?: boolean // 是否只使用3D场景\n selectionIndicator?: boolean // 选择指示器\n navigationHelpButton?: boolean // 导航帮助按钮\n fullscreenButton?: boolean // 全屏按钮\n geocoder?: boolean // 地理编码器\n homeButton?: boolean // 主页按钮\n infoBox?: boolean // 信息框\n vrButton?: boolean // VR按钮\n sceneModePicker?: boolean // 场景模式选择器\n timeline?: boolean // 时间轴\n animation?: boolean // 动画\n baseLayerPicker?: boolean // 基础图层选择器\n navigationInstructionsInitiallyVisible?: boolean // 导航指令初始可见\n clock?: Cesium.Clock // 时钟\n sceneMode?: Cesium.SceneMode // 场景模式\n screenSpaceEventHandler?: Cesium.ScreenSpaceEventHandler // 屏幕空间事件处理器\n useDefaultRenderLoop?: boolean // 使用默认渲染循环\n targetFrameRate?: number // 目标帧率\n showRenderLoopErrors?: boolean // 显示渲染循环错误\n automaticallyTrackDataSourceClocks?: boolean // 自动跟踪数据源时钟\n dataSources?: Cesium.DataSourceCollection // 数据源集合\n creationTime?: number // 创建时间\n useBrowserRecommendedResolution?: boolean // 使用浏览器推荐分辨率\n resolutionScale?: number // 分辨率缩放\n orderIndependentTransparency?: boolean // 无序透明度\n shadows?: boolean // 阴影\n terrainExaggeration?: number // 地形夸张系数\n maximumScreenSpaceError?: number // 最大屏幕空间误差\n maximumNumberOfLoadedTiles?: number // 最大加载瓦片数量\n}\n\ninterface MapCenter {\n latitude: number\n longitude: number\n height: number,\n pitch?: number\n heading?: number\n}\n\ninterface TianDiMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\ninterface GaoDeMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\n\nexport function createTianDiMap(): TianDiMap {\n return {\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n }\n}\n\nexport function createGaoDeMap(): Cesium.UrlTemplateImageryProvider {\n return new Cesium.UrlTemplateImageryProvider({\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n })\n}\n\nexport async function initCesium(\n containerId: string,\n options: InitOptions,\n mapCenter: MapCenter = { longitude: 120.2052342, latitude: 30.2489634, height: 1000, pitch: -60, heading: 0 }\n): Promise<{ viewer: CesiumViewer; initialCenter: MapCenter }> {\n Ion.defaultAccessToken = (import.meta as any).env.VITE_CESIUM_TOKEN\n const viewer = new Viewer(containerId, {\n timeline: false,\n animation: false,\n baseLayerPicker: false,\n ...options\n })\n // 地形提供者\n if (!options.terrainProvider && !options.terrain) {\n viewer.terrainProvider = await createWorldTerrainAsync()\n }\n // 添加高德图影像图层\n if (options.mapType === 'gaode') {\n viewer.imageryLayers.removeAll();\n viewer.imageryLayers.addImageryProvider(createGaoDeMap());\n }\n if (mapCenter) {\n // 设置初始视角为中国区域 (经度, 纬度, 高度)\n viewer.camera.flyTo({\n destination: Cesium.Cartesian3.fromDegrees(mapCenter.longitude, mapCenter.latitude, mapCenter.height), // 中国中心坐标\n orientation: {\n heading: Cesium.Math.toRadians(mapCenter.heading || 0), // 方向角度\n pitch: Cesium.Math.toRadians(mapCenter.pitch || -30), // 俯\n }\n });\n }\n (viewer.cesiumWidget.creditContainer as HTMLElement).style.display = 'none';\n return { viewer, initialCenter: mapCenter }\n}","// VMap Cesium Toolbar Plugin\r\n// 导出主要类和接口\r\n\r\n// 核心类\r\nexport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nexport { default as DrawHelper } from './libs/CesiumMapHelper';\r\nexport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 类型定义\r\nexport type {\r\n ToolbarConfig,\r\n ButtonConfig,\r\n CustomButtonConfig,\r\n SearchCallback,\r\n SearchResult,\r\n MeasurementCallback,\r\n ZoomCallback,\r\n MapType\r\n} from './libs/CesiumMapToolbar';\r\n\r\nexport type {\r\n FrustumOptions,\r\n OverlayOptions\r\n} from './libs/CesiumMapModel';\r\n\r\n// 导入用于默认导出\r\nimport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nimport DrawHelper from './libs/CesiumMapHelper';\r\nimport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 默认导出\r\nexport default {\r\n CesiumMapToolbar,\r\n DrawHelper,\r\n initCesium\r\n};\r\n"],"names":["DrawHelper","viewer","Cesium","height","primitive","options","fov","aspectRatio","near","far","position","orientation","frustum","fillGeometry","fillInstance","fillPrimitive","outlineGeometry","outlineInstance","outlinePrimitive","movement","error","mode","click","cartesian","move","mapDoubleClickAct","dblClick","windowPosition","ray","carto","elevatedPosition","pointEntity","entity","currentMousePosition","previewPoint","entitiesToRemove","index","positions","activeEntity","elevatedPositions","pos","i","startPos","endPos","distance","midPoint","labelOffset","labelEntity","totalDistance","labelPosition","totalLabelEntity","rect","finalEntity","p","area","center","areaLabelEntity","rectCenter","rectAreaLabelEntity","resetMode","allEntities","p1","p2","cartographic1","cartographic2","west","east","south","north","width","ellipsoid","len","x","y","z","callback","longitude","latitude","radius","borderColor","fillColor","borderWidth","name","color","groundHeight","groundPosition","topPosition","CesiumMapToolbar","container","config","callbacks","initialCenter","buttonId","button","buttonConfig","buttonElement","btn","defaultButtons","customButton","buttonSize","buttonColor","buttonHoverColor","icon","e","measureMenu","layersMenu","existingSearch","searchContainer","searchInput","resultsContainer","searchTimeout","query","results","closeSearchOnClickOutside","event","closeSearchOnEscape","result","resultItem","mockResults","menu","item","menuItem","closeMenu","action","targetMode","mapTypeSection","mapType","mapTypeItem","thumbnail","label","checkmark","mapTypeId","mt","beforeLevel","afterLevel","fullscreenChange","createGaoDeMap","initCesium","containerId","mapCenter","Ion","Viewer","createWorldTerrainAsync"],"mappings":"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"}
|