| @@ -78,11 +78,13 @@ const PathEventType = { | |||
| const PlotEventType = { | |||
| DRAW_START: 'drawStart', | |||
| DRAW_MOVING: 'drawMoving', | |||
| DARW_END: 'drawEnd', | |||
| DRAW_STOP: 'drawStop', | |||
| EDIT_START: 'editStart', | |||
| EDIT_END: 'editEnd', | |||
| EDIT_STOP: 'editEnd', | |||
| ADD_ANCHOR: 'addAnchor', | |||
| ANCHOR_MOVING: 'anchorMoving' | |||
| ANCHOR_MOVING: 'anchorMoving', | |||
| EDIT_ANCHOR_STOP: 'editAnchorStop', | |||
| CLEAR_ANCHOR: 'clearAnchor' | |||
| } | |||
| export { | |||
| @@ -0,0 +1,213 @@ | |||
| /** | |||
| * @Author: Caven | |||
| * @Date: 2021-07-14 20:28:14 | |||
| */ | |||
| import { Cesium } from '@dc-modules/namespace' | |||
| import { MouseEventType, PlotEventType, PlotEvent } from '@dc-modules/event' | |||
| const IMG_CIRCLE_RED = require('@dc-modules/images/circle_red.png') | |||
| const IMG_CIRCLE_YELLOW = require('@dc-modules/images/circle_yellow.png') | |||
| const DEF_OPTS = { | |||
| icon_center: IMG_CIRCLE_YELLOW, | |||
| icon_anchor: IMG_CIRCLE_RED, | |||
| icon_size: [12, 12], | |||
| clampToModel: false | |||
| } | |||
| class DrawTool { | |||
| constructor() { | |||
| this._viewer = undefined | |||
| this._anchorLayer = new Cesium.CustomDataSource('draw-anchor-layer') | |||
| this._floatingAnchor = undefined | |||
| this._options = {} | |||
| this._plotEvent = new PlotEvent() | |||
| this._tooltipMess = undefined | |||
| } | |||
| set tooltipMess(tooltipMess) { | |||
| this._tooltipMess = tooltipMess | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param e | |||
| * @returns {boolean} | |||
| * @private | |||
| */ | |||
| _onClick(e) { | |||
| let position = | |||
| this._options.clampToModel && e.position ? e.position : e.surfacePosition | |||
| if (!position) { | |||
| return false | |||
| } | |||
| if (!this._floatingAnchor) { | |||
| this._floatingAnchor = this._onAddAnchor({ position }) | |||
| } | |||
| this._plotEvent.fire(PlotEventType.ADD_ANCHOR, position) | |||
| } | |||
| /** | |||
| * | |||
| * @param e | |||
| * @private | |||
| */ | |||
| _onMouseMove(e) { | |||
| this._viewer.tooltip.showAt(e.windowPosition, this._tooltipMess) | |||
| let position = | |||
| this._options.clampToModel && e.position ? e.position : e.surfacePosition | |||
| if (!position) { | |||
| return false | |||
| } | |||
| this._floatingAnchor && this._floatingAnchor.position.setValue(position) | |||
| this._plotEvent.fire(PlotEventType.DRAW_MOVING, position) | |||
| } | |||
| /** | |||
| * | |||
| * @param e | |||
| * @private | |||
| */ | |||
| _onRightClick(e) { | |||
| this._plotEvent.fire( | |||
| PlotEventType.DRAW_STOP, | |||
| this._options.clampToModel && e.position ? e.position : e.surfacePosition | |||
| ) | |||
| } | |||
| /** | |||
| * | |||
| * @param position | |||
| * @param isCenter | |||
| * @returns {*} | |||
| * @private | |||
| */ | |||
| _onAddAnchor({ position, isCenter = false }) { | |||
| this._anchorLayer.entities.add({ | |||
| position: position, | |||
| billboard: { | |||
| image: isCenter ? this._options.icon_center : this._options.icon_anchor, | |||
| width: this._options.icon_size[0], | |||
| height: this._options.icon_size[1], | |||
| eyeOffset: new Cesium.Cartesian3(0, 0, -500), | |||
| heightReference: | |||
| this._viewer.scene.mode === Cesium.SceneMode.SCENE3D && | |||
| !this._options.clampToModel | |||
| ? Cesium.HeightReference.CLAMP_TO_GROUND | |||
| : Cesium.HeightReference.NONE | |||
| } | |||
| }) | |||
| } | |||
| /** | |||
| * | |||
| * @private | |||
| */ | |||
| _onClearAnchor() { | |||
| this._anchorLayer.entities.removeAll() | |||
| } | |||
| /** | |||
| * | |||
| * @private | |||
| */ | |||
| _bindEvent() { | |||
| this._viewer.on(MouseEventType.CLICK, this._onClick, this) | |||
| this._viewer.on(MouseEventType.MOUSE_MOVE, this._onMouseMove, this) | |||
| this._viewer.on(MouseEventType.RIGHT_CLICK, this._onRightClick, this) | |||
| this.on(PlotEventType.ADD_ANCHOR, this._onAddAnchor, this) | |||
| this.on(PlotEventType.CLEAR_ANCHOR, this._onClearAnchor, this) | |||
| } | |||
| /** | |||
| * | |||
| * @private | |||
| */ | |||
| _unbindEvent() { | |||
| this._viewer.off(MouseEventType.CLICK, this._onClick, this) | |||
| this._viewer.off(MouseEventType.MOUSE_MOVE, this._onMouseMove, this) | |||
| this._viewer.off(MouseEventType.RIGHT_CLICK, this._onRightClick, this) | |||
| this.off(PlotEventType.ADD_ANCHOR, this._onAddAnchor, this) | |||
| this.off(PlotEventType.CLEAR_ANCHOR, this._onClearAnchor, this) | |||
| } | |||
| /** | |||
| * | |||
| * @param type | |||
| * @param callback | |||
| * @param context | |||
| * @returns {DrawTool} | |||
| */ | |||
| on(type, callback, context) { | |||
| this._plotEvent.on(type, callback, context || this) | |||
| this._plotEvent.on(type, callback, context || this) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param type | |||
| * @param callback | |||
| * @param context | |||
| * @returns {DrawTool} | |||
| */ | |||
| off(type, callback, context) { | |||
| this._plotEvent.off(type, callback, context || this) | |||
| this._plotEvent.off(type, callback, context || this) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param type | |||
| * @param parmas | |||
| * @returns {DrawTool} | |||
| */ | |||
| fire(type, parmas) { | |||
| this._plotEvent.fire(type, parmas) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param options | |||
| * @returns {DrawTool} | |||
| */ | |||
| activate(options = {}) { | |||
| this._viewer.tooltip.enable = true | |||
| this._options = { ...DEF_OPTS, ...options } | |||
| this._unbindEvent() | |||
| this._bindEvent() | |||
| this.fire(PlotEventType.DRAW_START, this._options) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @returns {DrawTool} | |||
| */ | |||
| deactivate() { | |||
| this._unbindEvent() | |||
| this._viewer.tooltip.enable = false | |||
| this._anchorLayer.entities.removeAll() | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param viewer | |||
| */ | |||
| install(viewer) { | |||
| this._viewer = viewer | |||
| this._viewer.dataSources.add(this._anchorLayer) | |||
| Object.defineProperty(this._viewer, 'drawTool', { | |||
| value: this, | |||
| writable: false | |||
| }) | |||
| } | |||
| } | |||
| export default DrawTool | |||
| @@ -0,0 +1,280 @@ | |||
| /** | |||
| * @Author: Caven | |||
| * @Date: 2021-07-14 20:28:10 | |||
| */ | |||
| import { Cesium } from '@dc-modules/namespace' | |||
| import { MouseEventType, PlotEventType, PlotEvent } from '@dc-modules/event' | |||
| const IMG_CIRCLE_RED = require('@dc-modules/images/circle_red.png') | |||
| const IMG_CIRCLE_BLUE = require('@dc-modules/images/circle_blue.png') | |||
| const IMG_CIRCLE_YELLOW = require('@dc-modules/images/circle_yellow.png') | |||
| const DEF_OPTS = { | |||
| icon_center: IMG_CIRCLE_YELLOW, | |||
| icon_anchor: IMG_CIRCLE_RED, | |||
| icon_midAnchor: IMG_CIRCLE_BLUE, | |||
| icon_size: [12, 12], | |||
| clampToModel: true | |||
| } | |||
| class EditTool { | |||
| constructor() { | |||
| this._viewer = undefined | |||
| this._anchorLayer = new Cesium.CustomDataSource('edit-anchor-layer') | |||
| this._options = {} | |||
| this._plotEvent = new PlotEvent() | |||
| this._tooltipMess = undefined | |||
| this._pickedAnchor = undefined | |||
| this._isMoving = false | |||
| this._anchors = [] | |||
| } | |||
| set tooltipMess(tooltipMess) { | |||
| this._tooltipMess = tooltipMess | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param e | |||
| * @returns {boolean} | |||
| * @private | |||
| */ | |||
| _onClick(e) { | |||
| if (this._isMoving) { | |||
| let position = | |||
| this._options.clampToModel && e.position | |||
| ? e.position | |||
| : e.surfacePosition | |||
| if (!position) { | |||
| return false | |||
| } | |||
| if ( | |||
| this._pickedAnchor && | |||
| this._pickedAnchor.position && | |||
| this._pickedAnchor.properties | |||
| ) { | |||
| let properties = this._pickedAnchor.properties.getValue( | |||
| Cesium.JulianDate.now() | |||
| ) | |||
| this._pickedAnchor.position.setValue(position) | |||
| this._plotEvent.fire(PlotEventType.EDIT_ANCHOR_STOP, { | |||
| index: properties.index, | |||
| position: position | |||
| }) | |||
| } | |||
| this._isMoving = false | |||
| } else { | |||
| if (!e.target || !e.target.id) { | |||
| return false | |||
| } | |||
| this._pickedAnchor = e.target.id | |||
| this._isMoving = true | |||
| } | |||
| } | |||
| /** | |||
| * | |||
| * @param e | |||
| * @private | |||
| */ | |||
| _onMouseMove(e) { | |||
| this._viewer.tooltip.showAt(e.windowPosition, this._tooltipMess) | |||
| if (!this._isMoving) { | |||
| return false | |||
| } | |||
| let position = | |||
| this._options.clampToModel && e.position ? e.position : e.surfacePosition | |||
| if (!position) { | |||
| return false | |||
| } | |||
| if ( | |||
| this._pickedAnchor && | |||
| this._pickedAnchor.position && | |||
| this._pickedAnchor.properties | |||
| ) { | |||
| let properties = this._pickedAnchor.properties.getValue( | |||
| Cesium.JulianDate.now() | |||
| ) | |||
| this._pickedAnchor.position.setValue(position) | |||
| this._plotEvent.fire(PlotEventType.ANCHOR_MOVING, { | |||
| index: properties.index, | |||
| position: position | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * | |||
| * @param e | |||
| * @private | |||
| */ | |||
| _onRightClick(e) { | |||
| this._plotEvent.fire( | |||
| PlotEventType.DRAW_STOP, | |||
| this._options.clampToModel && e.position ? e.position : e.surfacePosition | |||
| ) | |||
| } | |||
| /** | |||
| * | |||
| * @param position | |||
| * @param index | |||
| * @param isCenter | |||
| * @param isMid | |||
| * @private | |||
| */ | |||
| _onAddAnchor({ position, index, isCenter = false, isMid = false }) { | |||
| let image = isMid | |||
| ? this._options.icon_midAnchor | |||
| : isCenter | |||
| ? this._options.icon_center | |||
| : this._options.icon_anchor | |||
| let anchor = this._anchorLayer.add({ | |||
| position: position, | |||
| billboard: { | |||
| image: image, | |||
| width: 12, | |||
| height: 12, | |||
| eyeOffset: new Cesium.ConstantProperty( | |||
| new Cesium.Cartesian3(0, 0, -500) | |||
| ), | |||
| heightReference: | |||
| this._viewer.scene.mode === Cesium.SceneMode.SCENE3D && | |||
| !this._options.clampToModel | |||
| ? Cesium.HeightReference.CLAMP_TO_GROUND | |||
| : Cesium.HeightReference.NONE | |||
| }, | |||
| properties: { | |||
| isMid: isMid, | |||
| index: index | |||
| } | |||
| }) | |||
| this._anchors.push(anchor) | |||
| } | |||
| /** | |||
| * | |||
| * @private | |||
| */ | |||
| _onClearAnchor() { | |||
| this._anchorLayer.entities.removeAll() | |||
| } | |||
| /** | |||
| * | |||
| * @private | |||
| */ | |||
| _bindEvent() { | |||
| this._viewer.on(MouseEventType.CLICK, this._onClick, this) | |||
| this._viewer.on(MouseEventType.MOUSE_MOVE, this._onMouseMove, this) | |||
| this._viewer.on(MouseEventType.RIGHT_CLICK, this._onRightClick, this) | |||
| this.on(PlotEventType.ADD_ANCHOR, this._onAddAnchor, this) | |||
| this.on(PlotEventType.CLEAR_ANCHOR, this._onClearAnchor, this) | |||
| } | |||
| /** | |||
| * | |||
| * @private | |||
| */ | |||
| _unbindEvent() { | |||
| this._viewer.off(MouseEventType.CLICK, this._onClick, this) | |||
| this._viewer.off(MouseEventType.MOUSE_MOVE, this._onMouseMove, this) | |||
| this._viewer.off(MouseEventType.RIGHT_CLICK, this._onRightClick, this) | |||
| this.off(PlotEventType.ADD_ANCHOR, this._onAddAnchor, this) | |||
| this.off(PlotEventType.CLEAR_ANCHOR, this._onClearAnchor, this) | |||
| } | |||
| /** | |||
| * | |||
| * @param p1 | |||
| * @param p2 | |||
| * @returns {Cartesian3} | |||
| */ | |||
| computeMidPosition(p1, p2) { | |||
| let c1 = Cesium.Ellipsoid.WGS84.cartesianToCartographic(p1) | |||
| let c2 = Cesium.Ellipsoid.WGS84.cartesianToCartographic(p2) | |||
| let cm = new Cesium.EllipsoidGeodesic(c1, c2).interpolateUsingFraction(0.5) | |||
| return Cesium.Ellipsoid.WGS84.cartographicToCartesian(cm) | |||
| } | |||
| /** | |||
| * | |||
| * @param type | |||
| * @param callback | |||
| * @param context | |||
| * @returns {EditTool} | |||
| */ | |||
| on(type, callback, context) { | |||
| this._plotEvent.on(type, callback, context || this) | |||
| this._plotEvent.on(type, callback, context || this) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param type | |||
| * @param callback | |||
| * @param context | |||
| * @returns {EditTool} | |||
| */ | |||
| off(type, callback, context) { | |||
| this._plotEvent.off(type, callback, context || this) | |||
| this._plotEvent.off(type, callback, context || this) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param type | |||
| * @param parmas | |||
| * @returns {EditTool} | |||
| */ | |||
| fire(type, parmas) { | |||
| this._plotEvent.fire(type, parmas) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param options | |||
| * @returns {EditTool} | |||
| */ | |||
| activate(options = {}) { | |||
| this._viewer.tooltip.enable = true | |||
| this._options = { ...DEF_OPTS, ...options } | |||
| this._unbindEvent() | |||
| this._bindEvent() | |||
| this.fire(PlotEventType.DRAW_START, this._options) | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @returns {EditTool} | |||
| */ | |||
| deactivate() { | |||
| this._unbindEvent() | |||
| this._viewer.tooltip.enable = false | |||
| this._anchorLayer.entities.removeAll() | |||
| return this | |||
| } | |||
| /** | |||
| * | |||
| * @param viewer | |||
| */ | |||
| install(viewer) { | |||
| this._viewer = viewer | |||
| this._viewer.dataSources.add(this._anchorLayer) | |||
| Object.defineProperty(this._viewer, 'editTool', { | |||
| value: this, | |||
| writable: false | |||
| }) | |||
| } | |||
| } | |||
| export default EditTool | |||
| @@ -0,0 +1,14 @@ | |||
| /** | |||
| * @Author: Caven | |||
| * @Date: 2021-07-14 20:25:41 | |||
| */ | |||
| import DrawTool from './DrawTool' | |||
| import EditTool from './EditTool' | |||
| export default function createTools() { | |||
| return { | |||
| drawTool: new DrawTool(), | |||
| editTool: new EditTool() | |||
| } | |||
| } | |||
| @@ -16,6 +16,7 @@ import { ViewerOption, CameraOption } from '@dc-modules/option' | |||
| import { Util, DomUtil } from '@dc-modules/utils' | |||
| import { Transform } from '@dc-modules/transform' | |||
| import createWidgets from '@dc-modules/widget' | |||
| import createTools from '@dc-modules/tools' | |||
| const DEF_OPTS = { | |||
| animation: false, //Whether to create animated widgets, lower left corner of the meter | |||
| @@ -75,6 +76,14 @@ class Viewer { | |||
| Object.keys(widgets).forEach(key => { | |||
| this.use(widgets[key]) | |||
| }) | |||
| /** | |||
| * Registers default tools | |||
| */ | |||
| let tools = createTools() | |||
| Object.keys(tools).forEach(key => { | |||
| this.use(tools[key]) | |||
| }) | |||
| } | |||
| get delegate() { | |||