|
|
|
@ -26,6 +26,14 @@ |
|
|
|
top: hoverTooltip.position.y + 'px' |
|
|
|
}" |
|
|
|
/> |
|
|
|
<context-menu |
|
|
|
v-if="contextMenu.visible" |
|
|
|
:visible="contextMenu.visible" |
|
|
|
:position="contextMenu.position" |
|
|
|
:entity-data="contextMenu.entityData" |
|
|
|
@delete="deleteEntityFromContextMenu" |
|
|
|
@update-property="updateEntityProperty" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<script> |
|
|
|
@ -34,6 +42,7 @@ import 'cesium/Build/Cesium/Widgets/widgets.css' |
|
|
|
import DrawingToolbar from './DrawingToolbar.vue' |
|
|
|
import MeasurementPanel from './MeasurementPanel.vue' |
|
|
|
import HoverTooltip from './HoverTooltip.vue' |
|
|
|
import ContextMenu from './ContextMenu.vue' |
|
|
|
import axios from 'axios' |
|
|
|
import request from '@/utils/request' |
|
|
|
import { getToken } from '@/utils/auth' |
|
|
|
@ -90,6 +99,12 @@ export default { |
|
|
|
content: '', |
|
|
|
position: { x: 0, y: 0 } |
|
|
|
}, |
|
|
|
// 右键菜单 |
|
|
|
contextMenu: { |
|
|
|
visible: false, |
|
|
|
position: { x: 0, y: 0 }, |
|
|
|
entityData: null |
|
|
|
}, |
|
|
|
// 默认样式 |
|
|
|
defaultStyles: { |
|
|
|
point: { color: '#FF0000', size: 12 }, |
|
|
|
@ -107,7 +122,8 @@ export default { |
|
|
|
components: { |
|
|
|
DrawingToolbar, |
|
|
|
MeasurementPanel, |
|
|
|
HoverTooltip |
|
|
|
HoverTooltip, |
|
|
|
ContextMenu |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
console.log(this.drawDomClick,999999) |
|
|
|
@ -430,6 +446,9 @@ export default { |
|
|
|
// 1. 定义全局拾取处理器 |
|
|
|
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); |
|
|
|
this.handler.setInputAction((click) => { |
|
|
|
// 隐藏右键菜单 |
|
|
|
this.contextMenu.visible = false; |
|
|
|
|
|
|
|
if (this.isDrawing) return; |
|
|
|
|
|
|
|
const pickedObject = this.viewer.scene.pick(click.position); |
|
|
|
@ -463,12 +482,16 @@ export default { |
|
|
|
initRightClickHandler() { |
|
|
|
// 创建屏幕空间事件处理器 |
|
|
|
this.rightClickHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) |
|
|
|
// 右键点击事件:删除单个实体 |
|
|
|
// 右键点击事件:显示上下文菜单 |
|
|
|
this.rightClickHandler.setInputAction((click) => { |
|
|
|
// 如果正在绘制,不处理删除操作 |
|
|
|
// 如果正在绘制,不处理右键操作 |
|
|
|
if (this.isDrawing) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 隐藏之前可能显示的菜单 |
|
|
|
this.contextMenu.visible = false; |
|
|
|
|
|
|
|
const pickedObject = this.viewer.scene.pick(click.position) |
|
|
|
if (Cesium.defined(pickedObject) && pickedObject.id) { |
|
|
|
const pickedEntity = pickedObject.id |
|
|
|
@ -487,14 +510,15 @@ export default { |
|
|
|
} |
|
|
|
} |
|
|
|
if (entityData) { |
|
|
|
// 显示确认对话框 |
|
|
|
if (confirm('确定要删除这个对象吗?')) { |
|
|
|
if (entityData.id) { |
|
|
|
this.removeEntity(entityData.id) |
|
|
|
} else if (entityData.entity && entityData.entity.id) { |
|
|
|
this.removeEntity(entityData.entity.id) |
|
|
|
} |
|
|
|
} |
|
|
|
// 显示上下文菜单 |
|
|
|
this.contextMenu = { |
|
|
|
visible: true, |
|
|
|
position: { |
|
|
|
x: click.position.x, |
|
|
|
y: click.position.y |
|
|
|
}, |
|
|
|
entityData: entityData |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK) |
|
|
|
@ -1076,19 +1100,32 @@ export default { |
|
|
|
this.tempEntity = null; |
|
|
|
} |
|
|
|
// 3. 创建最终显示的静态实体 |
|
|
|
this.entityCounter++; |
|
|
|
const id = `rectangle_${this.entityCounter}`; |
|
|
|
const finalEntity = this.viewer.entities.add({ |
|
|
|
id: 'rectangle-' + new Date().getTime(), // 给个唯一ID |
|
|
|
id: id, |
|
|
|
rectangle: { |
|
|
|
coordinates: rect, |
|
|
|
material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5), |
|
|
|
material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(this.defaultStyles.polygon.opacity), |
|
|
|
outline: true, |
|
|
|
outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.line.color), |
|
|
|
outlineWidth: 2, |
|
|
|
outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color), |
|
|
|
outlineWidth: this.defaultStyles.polygon.width, |
|
|
|
clampToGround: true |
|
|
|
} |
|
|
|
}); |
|
|
|
// 4. 记录到实体列表 |
|
|
|
this.allEntities.push(finalEntity); |
|
|
|
const entityData = { |
|
|
|
id: id, |
|
|
|
type: 'rectangle', |
|
|
|
points: this.drawingPoints.map(p => this.cartesianToLatLng(p)), |
|
|
|
positions: this.drawingPoints, |
|
|
|
entity: finalEntity, |
|
|
|
color: this.defaultStyles.polygon.color, |
|
|
|
opacity: this.defaultStyles.polygon.opacity, |
|
|
|
width: this.defaultStyles.polygon.width, |
|
|
|
label: `矩形 ${this.entityCounter}` |
|
|
|
}; |
|
|
|
this.allEntities.push(entityData); |
|
|
|
// 5. 计算并显示面积 |
|
|
|
const area = this.calculateRectangleArea(rect); |
|
|
|
this.measurementResult = { |
|
|
|
@ -1259,20 +1296,34 @@ export default { |
|
|
|
this.tempEntity = null; |
|
|
|
} |
|
|
|
// 3. 创建最终显示的静态实体 |
|
|
|
this.entityCounter++; |
|
|
|
const id = `circle_${this.entityCounter}`; |
|
|
|
const finalEntity = this.viewer.entities.add({ |
|
|
|
id: 'circle-' + new Date().getTime(), |
|
|
|
id: id, |
|
|
|
position: centerPoint, |
|
|
|
ellipse: { |
|
|
|
semiMajorAxis: radius, |
|
|
|
semiMinorAxis: radius, |
|
|
|
material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5), |
|
|
|
material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(this.defaultStyles.polygon.opacity), |
|
|
|
outline: true, |
|
|
|
outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.line.color), |
|
|
|
outlineWidth: 2 |
|
|
|
outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color), |
|
|
|
outlineWidth: this.defaultStyles.polygon.width |
|
|
|
} |
|
|
|
}); |
|
|
|
// 4. 记录实体 |
|
|
|
this.allEntities.push(finalEntity); |
|
|
|
const entityData = { |
|
|
|
id: id, |
|
|
|
type: 'circle', |
|
|
|
points: [centerPoint, edgePosition].map(p => this.cartesianToLatLng(p)), |
|
|
|
positions: [centerPoint, edgePosition], |
|
|
|
entity: finalEntity, |
|
|
|
color: this.defaultStyles.polygon.color, |
|
|
|
opacity: this.defaultStyles.polygon.opacity, |
|
|
|
width: this.defaultStyles.polygon.width, |
|
|
|
radius: radius, |
|
|
|
label: `圆形 ${this.entityCounter}` |
|
|
|
}; |
|
|
|
this.allEntities.push(entityData); |
|
|
|
// 5. 计算面积 (π * r²) 并显示 |
|
|
|
// 半径单位是米,面积单位是平方米 |
|
|
|
const area = Math.PI * Math.pow(radius, 2); |
|
|
|
@ -2043,33 +2094,62 @@ export default { |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
updateEntityStyle() { |
|
|
|
if (!this.selectedEntity || !this.selectedEntity.entity) return |
|
|
|
const entity = this.selectedEntity.entity |
|
|
|
const data = this.selectedEntity |
|
|
|
updateEntityStyle(entityData = null) { |
|
|
|
const data = entityData || this.selectedEntity |
|
|
|
if (!data || !data.entity) return |
|
|
|
const entity = data.entity |
|
|
|
switch (data.type) { |
|
|
|
case 'point': |
|
|
|
if (entity.point) { |
|
|
|
entity.point.color = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.point.pixelSize = data.size |
|
|
|
} |
|
|
|
break |
|
|
|
case 'line': |
|
|
|
if (entity.polyline) { |
|
|
|
entity.polyline.material = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.polyline.width = data.width |
|
|
|
} |
|
|
|
break |
|
|
|
case 'polygon': |
|
|
|
if (entity.polygon) { |
|
|
|
entity.polygon.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity) |
|
|
|
entity.polygon.outlineColor = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.polygon.outlineWidth = data.width |
|
|
|
} |
|
|
|
break |
|
|
|
case 'rectangle': |
|
|
|
if (entity.rectangle) { |
|
|
|
entity.rectangle.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity) |
|
|
|
entity.rectangle.outlineColor = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.rectangle.outlineWidth = data.width |
|
|
|
} |
|
|
|
break |
|
|
|
case 'circle': |
|
|
|
if (entity.ellipse) { |
|
|
|
entity.ellipse.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity) |
|
|
|
entity.ellipse.outlineColor = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.ellipse.outlineWidth = data.width |
|
|
|
} |
|
|
|
break |
|
|
|
case 'sector': |
|
|
|
if (entity.polygon) { |
|
|
|
entity.polygon.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity) |
|
|
|
entity.polygon.outlineColor = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.polygon.outlineWidth = data.width |
|
|
|
} |
|
|
|
break |
|
|
|
case 'arrow': |
|
|
|
if (entity.polyline) { |
|
|
|
entity.polyline.material = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(data.color)) |
|
|
|
entity.polyline.width = data.width |
|
|
|
} |
|
|
|
break |
|
|
|
case 'text': |
|
|
|
if (entity.label) { |
|
|
|
entity.label.fillColor = Cesium.Color.fromCssColorString(data.color) |
|
|
|
entity.label.font = data.font |
|
|
|
} |
|
|
|
break |
|
|
|
} |
|
|
|
}, |
|
|
|
@ -2088,6 +2168,31 @@ export default { |
|
|
|
this.selectedEntity = null |
|
|
|
} |
|
|
|
}, |
|
|
|
// 从右键菜单删除实体 |
|
|
|
deleteEntityFromContextMenu() { |
|
|
|
if (this.contextMenu.entityData) { |
|
|
|
const entityData = this.contextMenu.entityData |
|
|
|
if (entityData.id) { |
|
|
|
this.removeEntity(entityData.id) |
|
|
|
} else if (entityData.entity && entityData.entity.id) { |
|
|
|
this.removeEntity(entityData.entity.id) |
|
|
|
} |
|
|
|
// 隐藏右键菜单 |
|
|
|
this.contextMenu.visible = false |
|
|
|
} |
|
|
|
}, |
|
|
|
// 更新实体属性 |
|
|
|
updateEntityProperty(property, value) { |
|
|
|
if (this.contextMenu.entityData) { |
|
|
|
const entityData = this.contextMenu.entityData |
|
|
|
// 更新实体数据 |
|
|
|
entityData[property] = value |
|
|
|
// 更新实体样式 |
|
|
|
this.updateEntityStyle(entityData) |
|
|
|
// 隐藏右键菜单 |
|
|
|
this.contextMenu.visible = false |
|
|
|
} |
|
|
|
}, |
|
|
|
removeEntity(id) { |
|
|
|
// 查找对应的实体数据 |
|
|
|
const index = this.allEntities.findIndex(e => |
|
|
|
|