吉安感知网项目-前端
shuishen
2026-01-28 046a69a1a3b50079eae3663cd631bd062748ec4f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import * as Cesium from 'cesium'
import { MapTooltip } from '../Tooltip'
import { ToolBase } from '../ToolBase'
import { buildEllipsePositions } from '../shapeUtils'
 
export class DrawBufferCircleTool extends ToolBase {
    constructor(viewer) {
        super(viewer)
        this.tooltip = new MapTooltip(viewer)
        this.dataSource = null
        this.circleEntity = null
        this.centerCartesian = null
        this.radius = 0
        this.isDrawing = false
    }
 
    start() {
        this.dataSource = new Cesium.CustomDataSource('draw-buffer-circle')
        this.viewer.dataSources.add(this.dataSource)
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
        this.handler.setInputAction(click => this.handleLeftClick(click), Cesium.ScreenSpaceEventType.LEFT_CLICK)
        this.handler.setInputAction(movement => this.handleMouseMove(movement), Cesium.ScreenSpaceEventType.MOUSE_MOVE)
        this.tooltip.show('单击设置中心点', { x: 0, y: 0 })
    }
 
    handleLeftClick(click) {
        const position = this.getPositionFromScreen(click.position)
        if (!position) return
 
        if (!this.centerCartesian) {
            this.centerCartesian = position
            this.radius = 1
            this.isDrawing = true
            this.createEntities()
            this.tooltip.show('单击结束绘制', click.position)
            return
        }
 
        if (this.isDrawing) {
            this.isDrawing = false
            const positions = buildEllipsePositions(this.centerCartesian, this.radius, this.radius)
            this.notify('getPolygonPositions', positions)
            this.tooltip.hide()
            this.clearPreviewEntities()
        }
    }
 
    handleMouseMove(movement) {
        if (!this.isDrawing) {
            this.tooltip.move(movement.endPosition)
            return
        }
        const position = this.getPositionFromScreen(movement.endPosition)
        if (!position) return
        this.radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position))
        this.tooltip.move(movement.endPosition)
    }
 
    createEntities() {
        if (this.circleEntity) return
        this.circleEntity = this.dataSource.entities.add({
            position: new Cesium.CallbackProperty(() => this.centerCartesian, false),
            ellipse: {
                semiMajorAxis: new Cesium.CallbackProperty(() => this.radius, false),
                semiMinorAxis: new Cesium.CallbackProperty(() => this.radius, false),
                material: Cesium.Color.fromBytes(45, 140, 240, 99),
                outline: true,
                outlineColor: Cesium.Color.fromBytes(45, 140, 240, 255),
                outlineWidth: 2,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            },
        })
    }
 
    clearPreviewEntities() {
        if (!this.dataSource) return
        this.dataSource.entities.removeAll()
        this.circleEntity = null
    }
 
    getSurfaceDistance(startCartesian, endCartesian) {
        const start = Cesium.Cartographic.fromCartesian(startCartesian)
        const end = Cesium.Cartographic.fromCartesian(endCartesian)
        const geodesic = new Cesium.EllipsoidGeodesic(start, end)
        return geodesic.surfaceDistance
    }
 
    getPositionFromScreen(screenPosition) {
        const scene = this.viewer.scene
        const cartesian = scene.pickPosition(screenPosition)
        if (cartesian) return cartesian
        return scene.camera.pickEllipsoid(screenPosition, scene.globe.ellipsoid)
    }
 
    destroy() {
        if (this.dataSource) {
            this.dataSource.entities.removeAll()
            this.viewer.dataSources.remove(this.dataSource)
            this.dataSource = null
        }
        if (this.handler) {
            this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
            this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
            this.handler.destroy()
            this.handler = null
        }
        this.tooltip?.destroy()
        this.tooltip = null
        this.centerCartesian = null
        this.radius = 0
        this.isDrawing = false
    }
}