| | |
| | | // ============ 发布订阅机制 ============ |
| | | |
| | | // 外部订阅数据变化 |
| | | subscribe (key, listener) { |
| | | subscribe(key, listener) { |
| | | this.listeners.push({ key, listener }) |
| | | } |
| | | |
| | | // 通知订阅者 |
| | | notify (key, data) { |
| | | notify(key, data) { |
| | | this.listeners.filter(subscriber => subscriber.key === key).forEach(subscriber => subscriber.listener(data)) |
| | | } |
| | | |
| | | // ============ 绘制相关 ============ |
| | | // 编辑图斑 |
| | | editThePatch (data) { |
| | | editThePatch(data) { |
| | | this.isPreviewMode = data |
| | | // 关闭编辑能力时隐藏端点/中点,并清空中点,避免残留交互 |
| | | if (!this.isPreviewMode) { |
| | |
| | | } |
| | | } |
| | | // 删除测区 |
| | | deleteTheArea (data) { |
| | | deleteTheArea(data) { |
| | | this.isDeleteTheArea = data |
| | | } |
| | | |
| | | // 开始绘制 |
| | | startDrawing () { |
| | | startDrawing() { |
| | | this.drawingMode = true |
| | | this.curPolygon = new Cesium.PolygonHierarchy() |
| | | |
| | |
| | | } |
| | | |
| | | // 创建多边形实体(含边界线) |
| | | createPolygonEntity () { |
| | | createPolygonEntity() { |
| | | this.polygonEntity = this.editPolygonDataSource.entities.add({ |
| | | name: DrawPolygon.ENTITY_NAMES.POLYGON, |
| | | id: DrawPolygon.ENTITY_NAMES.POLYGON_ID, |
| | |
| | | } |
| | | |
| | | // 创建端点实体 |
| | | createPointEntity (position, isAdd) { |
| | | createPointEntity(position, isAdd) { |
| | | const pointIndex = isAdd ? this.curPolygon.positions.length - 2 : this.curPolygon.positions.length - 1 |
| | | |
| | | this.editPolygonPointDataSource.entities.add({ |
| | |
| | | }) |
| | | } |
| | | |
| | | createMidPointEntity (startInd, position) { |
| | | createMidPointEntity(startInd, position) { |
| | | // 使用 CallbackProperty 让中点位置随端点拖拽实时计算 |
| | | // startInd 表示该中点属于边:(startInd) -> (startInd + 1) |
| | | const updatePosition = () => { |
| | |
| | | }) |
| | | } |
| | | |
| | | rebuildEditPoints () { |
| | | rebuildEditPoints() { |
| | | // 插入/删除端点后:端点实体 id 与 customData.ind 需要全量重建,保证索引与 positions 一致 |
| | | if (!this.isPreviewMode) return |
| | | if (!this.editPolygonPointDataSource || !this.curPolygon?.positions) return |
| | |
| | | }) |
| | | } |
| | | |
| | | rebuildMidPoints () { |
| | | rebuildMidPoints() { |
| | | // 仅在“顶点数量变化/切换编辑态”时维护中点实体数量 |
| | | // 拖拽过程中中点位置由 CallbackProperty 自动更新,不需要重建 |
| | | if (!this.isPreviewMode) return |
| | |
| | | }) |
| | | } |
| | | |
| | | insertPointFromMidPoint (midPointEntity) { |
| | | insertPointFromMidPoint(midPointEntity) { |
| | | // 点击中点:在对应边上插入一个新端点(白点),并立即进入拖拽态 |
| | | if (!this.isPreviewMode) return |
| | | if (!this.editingMode) return |
| | |
| | | this.notify('getPolygonPositions', this.curPolygon.positions) |
| | | } |
| | | // 清除不在范围内的点 |
| | | removeLastInvalidPoint () { |
| | | removeLastInvalidPoint() { |
| | | const posLen = this.curPolygon.positions.length |
| | | if (posLen === 0) return |
| | | |
| | |
| | | } |
| | | } |
| | | // 添加一个点 |
| | | addPosition (position, isAdd = true) { |
| | | addPosition(position, isAdd = true) { |
| | | // 第一个点要重复压入一次,形成动态绘制效果 |
| | | if (this.curPolygon.positions.length === 0 && isAdd) { |
| | | this.curPolygon.positions.push(position.clone()) |
| | |
| | | // ============ 鼠标事件 ============ |
| | | |
| | | // 鼠标左键按下(选中端点拖动) |
| | | handleLeftDown (movement) { |
| | | handleLeftDown(movement) { |
| | | if (!this.editingMode) return |
| | | |
| | | const pickedEntity = this.viewer.scene.pick(movement.position)?.id |
| | |
| | | } |
| | | |
| | | // 鼠标左键抬起(拖拽结束) |
| | | handleLeftUp () { |
| | | handleLeftUp() { |
| | | if (!(this.editingMode && this.curPolygon?.positions && this.draggedEntity)) return |
| | | |
| | | if (this.currentDragPointIsValid && this.isDragging) { |
| | |
| | | } |
| | | |
| | | // 鼠标移动 |
| | | handleMouseMove (movement) { |
| | | handleMouseMove(movement) { |
| | | if (!this.drawingMode && !this.editingMode) return |
| | | |
| | | const cartesian = this.viewer.scene.pickPosition(movement.endPosition) |
| | |
| | | } |
| | | |
| | | // 鼠标左键点击 |
| | | handleLeftClick (click) { |
| | | handleLeftClick(click) { |
| | | this.removeMenuPopup() |
| | | |
| | | const pickedAllEntity = this.viewer.scene.drillPick(click.position).filter(i => i.id) |
| | |
| | | } |
| | | |
| | | // 鼠标右键点击(弹出菜单) |
| | | handleRightClick (click) { |
| | | handleRightClick(click) { |
| | | const that = this |
| | | if (that.drawingMode) return |
| | | |
| | |
| | | // ============ 删除相关 ============ |
| | | |
| | | // 删除所有实体 |
| | | removeEntities () { |
| | | removeEntities() { |
| | | if (this.editPolygonDataSource) { |
| | | this.editPolygonDataSource.entities.removeAll() |
| | | this.editPolygonDataSource = null |
| | |
| | | } |
| | | |
| | | // 完成绘制 |
| | | finishDrawing () { |
| | | finishDrawing() { |
| | | this.curPolygon.positions.pop() |
| | | |
| | | if (this.curPolygon.positions.length >= 3) { |
| | |
| | | } |
| | | |
| | | // 删除多边形 |
| | | delPolygon () { |
| | | delPolygon() { |
| | | this.removeEntities() |
| | | this.removeMenuPopup() |
| | | this.notify('getPolygonPositions', []) |
| | | this.startDrawing() |
| | | } |
| | | // 删除图斑 |
| | | delSpot () { |
| | | delSpot() { |
| | | this.removeEntities() |
| | | this.isPreviewMode = true |
| | | this.startDrawing() |
| | | } |
| | | // 删除端点 |
| | | delPoint () { |
| | | delPoint() { |
| | | if (this.curPolygon.positions.length <= 3) { |
| | | this.removeMenuPopup() |
| | | return ElMessage.warning('端点不可少于3个') |
| | |
| | | // ============ 工具方法 ============ |
| | | |
| | | // 创建右键菜单 |
| | | createMenuPopup (type = 'polygon') { |
| | | createMenuPopup(type = 'polygon') { |
| | | const menuPopupVBox = document.createElement('div') |
| | | menuPopupVBox.id = 'planarPolygonEdit' |
| | | menuPopupVBox.className = 'planar-polygon-edit-tooltip' |
| | |
| | | } |
| | | |
| | | // 移除菜单 |
| | | removeMenuPopup () { |
| | | removeMenuPopup() { |
| | | const that = this |
| | | if (that.menuPopup) { |
| | | that.menuPopup.removeEventListener('click', that.delPolygon) |
| | |
| | | } |
| | | |
| | | // 更新多边形样式(正常/错误) |
| | | updatePolygonAppearance (polygonColor, lineColor) { |
| | | updatePolygonAppearance(polygonColor, lineColor) { |
| | | this.polygonEntity.polygon.material = polygonColor |
| | | this.polygonEntity.polyline.material = lineColor |
| | | } |
| | | |
| | | // 禁用地图交互 |
| | | disableMapControl () { |
| | | disableMapControl() { |
| | | const controller = this.viewer.scene.screenSpaceCameraController |
| | | controller.enableRotate = false |
| | | controller.enableTranslate = false |
| | |
| | | } |
| | | |
| | | // 启用地图交互 |
| | | enableMapControl () { |
| | | enableMapControl() { |
| | | const controller = this.viewer.scene.screenSpaceCameraController |
| | | controller.enableRotate = true |
| | | controller.enableTranslate = true |
| | |
| | | } |
| | | |
| | | // 检查多边形是否自交 |
| | | curDragPointIsValid (positions) { |
| | | curDragPointIsValid(positions) { |
| | | if (positions.length < 3) return true |
| | | |
| | | const cartographics = Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray(positions) |
| | |
| | | return intersections.features.length === 0 |
| | | } |
| | | // 初始化已有多边形 |
| | | async initPolygon (viewer, positions, isPurePreview = false) { |
| | | async initPolygon(viewer, positions, isPurePreview = false) { |
| | | this.initHandler(viewer) |
| | | this.isPureSpotPreview = isPurePreview |
| | | this.startDrawing() |
| | | let newPosition = positions.map(item => { |
| | | return Cesium.Cartesian3.fromDegrees(Number(item.lng), Number(item.lat), Number(item?.height||0)) |
| | | return Cesium.Cartesian3.fromDegrees(Number(item.lng), Number(item.lat), Number(item?.height || 0)) |
| | | }) |
| | | // 预览航线的时候调用 |
| | | if (!this.isPureSpotPreview) { |
| | |
| | | duration: 0.5, |
| | | }) |
| | | |
| | | const pointList = await getPointPositionsHeight(positions, viewer) |
| | | let pointList = await getPointPositionsHeight(positions, viewer) |
| | | flyVisual({ positionsData: pointList.map(item => [item.lng, item.lat, item.ASL]), viewer }) |
| | | |
| | | this.drawingMode = false |
| | |
| | | } |
| | | |
| | | // 初始化事件处理器 |
| | | initHandler (viewer) { |
| | | initHandler(viewer) { |
| | | this.viewer = viewer |
| | | this.startDrawing() |
| | | |
| | |
| | | } |
| | | |
| | | // 移除事件处理器 |
| | | removeHandler () { |
| | | removeHandler() { |
| | | if (this.handler) { |
| | | const eventTypes = [ |
| | | Cesium.ScreenSpaceEventType.LEFT_DOWN, |
| | |
| | | /** |
| | | * 销毁实例,释放资源 |
| | | */ |
| | | destroy () { |
| | | destroy() { |
| | | if (!this.viewer) return |
| | | |
| | | this.removeMenuPopup() |