| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-01-15 19:17:52 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import WidgetType from './WidgetType' | |||||
| class Widget { | |||||
| constructor() { | |||||
| this._viewer = undefined | |||||
| this._enable = false | |||||
| this._wrapper = undefined | |||||
| this._ready = false | |||||
| this.type = undefined | |||||
| } | |||||
| set enable(enable) { | |||||
| if (this._enable === enable) { | |||||
| return this | |||||
| } | |||||
| this._enable = enable | |||||
| this._state = this._enable ? State.ENABLED : State.DISABLED | |||||
| this._enableHook && this._enableHook() | |||||
| return this | |||||
| } | |||||
| get enable() { | |||||
| return this._enable | |||||
| } | |||||
| get state() { | |||||
| return this._state | |||||
| } | |||||
| /** | |||||
| * mount content | |||||
| * @private | |||||
| */ | |||||
| _mountContent() {} | |||||
| /** | |||||
| * binds event | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() {} | |||||
| /** | |||||
| * Unbinds event | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() {} | |||||
| /** | |||||
| * When enable modifies the hook executed, the subclass copies it as required | |||||
| * @private | |||||
| */ | |||||
| _enableHook() { | |||||
| !this._ready && this._mountContent() | |||||
| if (this._enable) { | |||||
| !this._wrapper.parentNode && | |||||
| this._viewer.dcContainer.appendChild(this._wrapper) | |||||
| this._bindEvent() | |||||
| } else { | |||||
| this._unbindEvent() | |||||
| this._wrapper.parentNode && | |||||
| this._viewer.dcContainer.removeChild(this._wrapper) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Updating the Widget location requires subclass overrides | |||||
| * @param windowCoord | |||||
| * @private | |||||
| */ | |||||
| _updateWindowCoord(windowCoord) {} | |||||
| /** | |||||
| * Hook for installed | |||||
| * @private | |||||
| */ | |||||
| _installHook() {} | |||||
| /** | |||||
| * Installs to viewer | |||||
| * @param viewer | |||||
| */ | |||||
| install(viewer) { | |||||
| this._viewer = viewer | |||||
| /** | |||||
| * do installHook | |||||
| */ | |||||
| this._installHook && this._installHook() | |||||
| this._state = State.INSTALLED | |||||
| } | |||||
| /** | |||||
| * Setting wrapper | |||||
| * @param wrapper | |||||
| * @returns {Widget} | |||||
| */ | |||||
| setWrapper(wrapper) { | |||||
| return this | |||||
| } | |||||
| /** | |||||
| * Setting widget content | |||||
| * @param content | |||||
| * @returns {Widget} | |||||
| */ | |||||
| setContent(content) { | |||||
| if (content && typeof content === 'string') { | |||||
| this._wrapper.innerHTML = content | |||||
| } else if (content && content instanceof Element) { | |||||
| while (this._wrapper.hasChildNodes()) { | |||||
| this._wrapper.removeChild(this._wrapper.firstChild) | |||||
| } | |||||
| this._wrapper.appendChild(content) | |||||
| } | |||||
| return this | |||||
| } | |||||
| /** | |||||
| * hide widget | |||||
| */ | |||||
| hide() { | |||||
| this._wrapper && | |||||
| (this._wrapper.style.cssText = ` | |||||
| visibility:hidden; | |||||
| `) | |||||
| } | |||||
| /** | |||||
| * Registers type | |||||
| * @param type | |||||
| */ | |||||
| static registerType(type) { | |||||
| if (type) { | |||||
| WidgetType[type.toLocaleUpperCase()] = type.toLocaleLowerCase() | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param type | |||||
| */ | |||||
| static getWidgetType(type) { | |||||
| return WidgetType[type.toLocaleUpperCase()] || undefined | |||||
| } | |||||
| } | |||||
| export default Widget |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-05-10 10:15:46 | |||||
| */ | |||||
| let WidgetType = {} | |||||
| export default WidgetType |
| /** | |||||
| * @Author:Caven | |||||
| * @Date:2020-03-05 21:53:35 | |||||
| */ | |||||
| import Attribution from './type/Attribution' | |||||
| import ContextMenu from './type/ContextMenu' | |||||
| import LocationBar from './type/LocationBar' | |||||
| import MapSplit from './type/MapSplit' | |||||
| import MapSwitch from './type/MapSwitch' | |||||
| import Popup from './type/Popup' | |||||
| import Tooltip from './type/Tooltip' | |||||
| import HawkeyeMap from './type/HawkeyeMap' | |||||
| import Compass from './type/Compass' | |||||
| import DistanceLegend from './type/DistanceLegend' | |||||
| import ZoomController from './type/ZoomController' | |||||
| import LoadingMask from './type/LoadingMask' | |||||
| export default function createWidgets() { | |||||
| return { | |||||
| attribution: new Attribution(), | |||||
| popup: new Popup(), | |||||
| contextMenu: new ContextMenu(), | |||||
| tooltip: new Tooltip(), | |||||
| mapSwitch: new MapSwitch(), | |||||
| mapSplit: new MapSplit(), | |||||
| locationBar: new LocationBar(), | |||||
| hawkeyeMap: new HawkeyeMap(), | |||||
| compass: new Compass(), | |||||
| distanceLegend: new DistanceLegend(), | |||||
| zoomController: new ZoomController(), | |||||
| loadingMask: new LoadingMask() | |||||
| } | |||||
| } |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-02-11 21:08:01 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import Icons from '@dc-modules/icons' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| class Attribution extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-attribution') | |||||
| this._wrapper.style.cssText = ` | |||||
| position: absolute; | |||||
| left: 2px; | |||||
| bottom: 2px; | |||||
| font-size: 14px; | |||||
| color: #a7a7a7; | |||||
| padding: 2px 5px; | |||||
| border-radius: 2px; | |||||
| user-select: none; | |||||
| display:flex; | |||||
| ` | |||||
| this._config = undefined | |||||
| this.type = Widget.getWidgetType('attribution') | |||||
| this._state = State.INSTALLED | |||||
| } | |||||
| _installHook() { | |||||
| let logo = DomUtil.create('img', '', this._wrapper) | |||||
| logo.src = Icons.logo | |||||
| let a = DomUtil.create('a', '', this._wrapper) | |||||
| a.innerHTML = '数字视觉' | |||||
| a.href = 'javascript:void(0)' | |||||
| a.onclick = () => { | |||||
| window.open('https://www.dvgis.cn') | |||||
| } | |||||
| a.style.cssText = `color:#a7a7a7;font-size:14px` | |||||
| this.enable = true | |||||
| } | |||||
| } | |||||
| Widget.registerType('attribution') | |||||
| export default Attribution |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-03-19 13:11:12 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import Icons from '@dc-modules/icons' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import { SceneEventType } from '@dc-modules/event' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| class Compass extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', `dc-compass`) | |||||
| this._compassRectangle = undefined | |||||
| this._outRing = undefined | |||||
| this._gyro = undefined | |||||
| this._rotation_marker = undefined | |||||
| this._orbitCursorAngle = 0 | |||||
| this._orbitCursorOpacity = 0.0 | |||||
| this._orbitLastTimestamp = 0 | |||||
| this._orbitFrame = undefined | |||||
| this._orbitIsLook = false | |||||
| this._rotateInitialCursorAngle = undefined | |||||
| this._rotateFrame = undefined | |||||
| this._mouseMoveHandle = undefined | |||||
| this._mouseUpHandle = undefined | |||||
| this.type = Widget.getWidgetType('compass') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'compass', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| this._wrapper.onmousedown = e => { | |||||
| this._handleMouseDown(e) | |||||
| } | |||||
| this._wrapper.ondblclick = e => { | |||||
| this._handleDoubleClick(e) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| this._viewer.on(SceneEventType.POST_RENDER, this._postRenderHandler, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() { | |||||
| this._viewer.off(SceneEventType.POST_RENDER, this._postRenderHandler, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _postRenderHandler() { | |||||
| let heading = this._viewer.camera.heading | |||||
| this._outRing && | |||||
| (this._outRing.style.cssText = ` | |||||
| transform : rotate(-${heading}rad); | |||||
| -webkit-transform : rotate(-${heading}rad); | |||||
| `) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| DomUtil.create('div', 'out-ring-bg', this._wrapper) | |||||
| this._outRing = DomUtil.parseDom(Icons.compass_outer, true, 'out-ring') | |||||
| this._wrapper.appendChild(this._outRing) | |||||
| this._gyro = DomUtil.parseDom(Icons.compass_inner, true, 'gyro') | |||||
| this._wrapper.appendChild(this._gyro) | |||||
| this._rotation_marker = DomUtil.parseDom( | |||||
| Icons.compass_rotation_marker, | |||||
| true, | |||||
| 'rotation_marker' | |||||
| ) | |||||
| this._wrapper.appendChild(this._rotation_marker) | |||||
| this._rotation_marker.style.visibility = 'hidden' | |||||
| this._ready = true | |||||
| } | |||||
| _handleMouseDown(e) { | |||||
| let scene = this._viewer.scene | |||||
| if (scene.mode === Cesium.SceneMode.MORPHING) { | |||||
| return true | |||||
| } | |||||
| this._compassRectangle = e.currentTarget.getBoundingClientRect() | |||||
| let maxDistance = this._compassRectangle.width / 2.0 | |||||
| let vector = this._getVector(e) | |||||
| let distanceFraction = Cesium.Cartesian2.magnitude(vector) / maxDistance | |||||
| if (distanceFraction < 50 / 145) { | |||||
| this._orbit(vector) | |||||
| } else if (distanceFraction < 1.0) { | |||||
| this._rotate(vector) | |||||
| } else { | |||||
| return true | |||||
| } | |||||
| } | |||||
| _handleDoubleClick(event) { | |||||
| let scene = this._viewer.scene | |||||
| let camera = scene.camera | |||||
| let sscc = scene.screenSpaceCameraController | |||||
| if (scene.mode === Cesium.SceneMode.MORPHING || !sscc.enableInputs) { | |||||
| return true | |||||
| } | |||||
| if ( | |||||
| scene.mode === Cesium.SceneMode.COLUMBUS_VIEW && | |||||
| !sscc.enableTranslate | |||||
| ) { | |||||
| return | |||||
| } | |||||
| if ( | |||||
| scene.mode === Cesium.SceneMode.SCENE3D || | |||||
| scene.mode === Cesium.SceneMode.COLUMBUS_VIEW | |||||
| ) { | |||||
| if (!sscc.enableLook) { | |||||
| return | |||||
| } | |||||
| if (scene.mode === Cesium.SceneMode.SCENE3D) { | |||||
| if (!sscc.enableRotate) { | |||||
| return | |||||
| } | |||||
| } | |||||
| } | |||||
| let center = this._getCameraFocus(true) | |||||
| if (!center) { | |||||
| return | |||||
| } | |||||
| let cameraPosition = scene.globe.ellipsoid.cartographicToCartesian( | |||||
| camera.positionCartographic | |||||
| ) | |||||
| let surfaceNormal = scene.globe.ellipsoid.geodeticSurfaceNormal(center) | |||||
| let focusBoundingSphere = new Cesium.BoundingSphere(center, 0) | |||||
| camera.flyToBoundingSphere(focusBoundingSphere, { | |||||
| offset: new Cesium.HeadingPitchRange( | |||||
| 0, | |||||
| Cesium.Math.PI_OVER_TWO - | |||||
| Cesium.Cartesian3.angleBetween(surfaceNormal, camera.directionWC), | |||||
| Cesium.Cartesian3.distance(cameraPosition, center) | |||||
| ), | |||||
| duration: 1.5 | |||||
| }) | |||||
| } | |||||
| _getCameraFocus(inWorldCoordinates) { | |||||
| let result = new Cesium.Cartesian3() | |||||
| let scene = this._viewer.scene | |||||
| let camera = scene.camera | |||||
| if (scene.mode === Cesium.SceneMode.MORPHING) { | |||||
| return undefined | |||||
| } | |||||
| if (this._viewer.delegate.trackedEntity) { | |||||
| result = this._viewer.delegate.trackedEntity.position.getValue( | |||||
| this._viewer.clock.currentTime | |||||
| ) | |||||
| } else { | |||||
| let rayScratch = new Cesium.Ray() | |||||
| rayScratch.origin = camera.positionWC | |||||
| rayScratch.direction = camera.directionWC | |||||
| result = scene.globe.pick(rayScratch, scene) | |||||
| } | |||||
| if (!result) { | |||||
| return undefined | |||||
| } | |||||
| if ( | |||||
| scene.mode === Cesium.SceneMode.SCENE2D || | |||||
| scene.mode === Cesium.SceneMode.COLUMBUS_VIEW | |||||
| ) { | |||||
| result = camera.worldToCameraCoordinatesPoint(result) | |||||
| let unprojectedScratch = new Cesium.Cartographic() | |||||
| if (inWorldCoordinates) { | |||||
| result = scene.globe.ellipsoid.cartographicToCartesian( | |||||
| scene.mapProjection.unproject(result, unprojectedScratch) | |||||
| ) | |||||
| } | |||||
| } else { | |||||
| if (!inWorldCoordinates) { | |||||
| result = camera.worldToCameraCoordinatesPoint(result) | |||||
| } | |||||
| } | |||||
| return result | |||||
| } | |||||
| _orbit(vector) { | |||||
| let scene = this._viewer.scene | |||||
| let sscc = scene.screenSpaceCameraController | |||||
| let camera = scene.camera | |||||
| if (scene.mode === Cesium.SceneMode.MORPHING || !sscc.enableInputs) { | |||||
| return | |||||
| } | |||||
| switch (scene.mode) { | |||||
| case Cesium.SceneMode.COLUMBUS_VIEW: | |||||
| if (sscc.enableLook) { | |||||
| break | |||||
| } | |||||
| if (!sscc.enableTranslate || !sscc.enableTilt) { | |||||
| return | |||||
| } | |||||
| break | |||||
| case Cesium.SceneMode.SCENE3D: | |||||
| if (sscc.enableLook) { | |||||
| break | |||||
| } | |||||
| if (!sscc.enableTilt || !sscc.enableRotate) { | |||||
| return | |||||
| } | |||||
| break | |||||
| case Cesium.SceneMode.SCENE2D: | |||||
| if (!sscc.enableTranslate) { | |||||
| return | |||||
| } | |||||
| break | |||||
| } | |||||
| this._mouseMoveHandle = e => { | |||||
| this._orbitMouseMoveFunction(e) | |||||
| } | |||||
| this._mouseUpHandle = () => { | |||||
| this._orbitMouseUpFunction() | |||||
| } | |||||
| document.removeEventListener('mousemove', this._mouseMoveHandle, false) | |||||
| document.removeEventListener('mouseup', this._mouseUpHandle, false) | |||||
| this._orbitLastTimestamp = Cesium.getTimestamp() | |||||
| if (this._viewer.delegate.trackedEntity) { | |||||
| this._orbitFrame = undefined | |||||
| this._orbitIsLook = false | |||||
| } else { | |||||
| let center = this._getCameraFocus(true) | |||||
| if (!center) { | |||||
| this._orbitFrame = Cesium.Transforms.eastNorthUpToFixedFrame( | |||||
| camera.positionWC, | |||||
| scene.globe.ellipsoid | |||||
| ) | |||||
| this._orbitIsLook = true | |||||
| } else { | |||||
| this._orbitFrame = Cesium.Transforms.eastNorthUpToFixedFrame( | |||||
| center, | |||||
| scene.globe.ellipsoid | |||||
| ) | |||||
| this._orbitIsLook = false | |||||
| } | |||||
| } | |||||
| this._rotation_marker.style.visibility = 'visible' | |||||
| this._gyro.className += ' gyro-active' | |||||
| document.addEventListener('mousemove', this._mouseMoveHandle, false) | |||||
| document.addEventListener('mouseup', this._mouseUpHandle, false) | |||||
| this._viewer.clock.onTick.addEventListener(this._orbitTickFunction, this) | |||||
| this._updateAngleAndOpacity(vector, this._compassRectangle.width) | |||||
| } | |||||
| _orbitTickFunction(e) { | |||||
| let scene = this._viewer.scene | |||||
| let camera = this._viewer.camera | |||||
| let timestamp = Cesium.getTimestamp() | |||||
| let deltaT = timestamp - this._orbitLastTimestamp | |||||
| let rate = ((this._orbitCursorOpacity - 0.5) * 2.5) / 1000 | |||||
| let distance = deltaT * rate | |||||
| let angle = this._orbitCursorAngle + Cesium.Math.PI_OVER_TWO | |||||
| let x = Math.cos(angle) * distance | |||||
| let y = Math.sin(angle) * distance | |||||
| let oldTransform | |||||
| if (this._orbitFrame) { | |||||
| oldTransform = Cesium.Matrix4.clone(camera.transform) | |||||
| camera.lookAtTransform(this._orbitFrame) | |||||
| } | |||||
| if (scene.mode === Cesium.SceneMode.SCENE2D) { | |||||
| camera.move( | |||||
| new Cesium.Cartesian3(x, y, 0), | |||||
| (Math.max(scene.canvas.clientWidth, scene.canvas.clientHeight) / 100) * | |||||
| camera.positionCartographic.height * | |||||
| distance | |||||
| ) | |||||
| } else { | |||||
| if (this._orbitIsLook) { | |||||
| camera.look(Cesium.Cartesian3.UNIT_Z, -x) | |||||
| camera.look(camera.right, -y) | |||||
| } else { | |||||
| camera.rotateLeft(x) | |||||
| camera.rotateUp(y) | |||||
| } | |||||
| } | |||||
| if (this._orbitFrame && oldTransform) { | |||||
| camera.lookAtTransform(oldTransform) | |||||
| } | |||||
| this._orbitLastTimestamp = timestamp | |||||
| } | |||||
| _updateAngleAndOpacity(vector, compassWidth) { | |||||
| let angle = Math.atan2(-vector.y, vector.x) | |||||
| this._orbitCursorAngle = Cesium.Math.zeroToTwoPi( | |||||
| angle - Cesium.Math.PI_OVER_TWO | |||||
| ) | |||||
| let distance = Cesium.Cartesian2.magnitude(vector) | |||||
| let maxDistance = compassWidth / 2.0 | |||||
| let distanceFraction = Math.min(distance / maxDistance, 1.0) | |||||
| this._orbitCursorOpacity = 0.5 * distanceFraction * distanceFraction + 0.5 | |||||
| this._rotation_marker.style.cssText = ` | |||||
| transform: rotate(-${this._orbitCursorAngle}rad); | |||||
| opacity: ${this._orbitCursorOpacity}` | |||||
| } | |||||
| _orbitMouseMoveFunction(e) { | |||||
| this._updateAngleAndOpacity( | |||||
| this._getVector(e), | |||||
| this._compassRectangle.width | |||||
| ) | |||||
| } | |||||
| _orbitMouseUpFunction() { | |||||
| document.removeEventListener('mousemove', this._mouseMoveHandle, false) | |||||
| document.removeEventListener('mouseup', this._mouseUpHandle, false) | |||||
| this._viewer.clock.onTick.removeEventListener(this._orbitTickFunction, this) | |||||
| this._mouseMoveHandle = undefined | |||||
| this._mouseUpHandle = undefined | |||||
| this._rotation_marker.style.visibility = 'hidden' | |||||
| this._gyro.className = this._gyro.className.replace(' gyro-active', '') | |||||
| } | |||||
| _rotate(vector) { | |||||
| let scene = this._viewer.scene | |||||
| let camera = scene.camera | |||||
| let sscc = scene.screenSpaceCameraController | |||||
| if ( | |||||
| scene.mode === Cesium.SceneMode.MORPHING || | |||||
| scene.mode === Cesium.SceneMode.SCENE2D || | |||||
| !sscc.enableInputs | |||||
| ) { | |||||
| return | |||||
| } | |||||
| if ( | |||||
| !sscc.enableLook && | |||||
| (scene.mode === Cesium.SceneMode.COLUMBUS_VIEW || | |||||
| (scene.mode === Cesium.SceneMode.SCENE3D && !sscc.enableRotate)) | |||||
| ) { | |||||
| return | |||||
| } | |||||
| this._mouseMoveHandle = e => { | |||||
| this._rotateMouseMoveFunction(e) | |||||
| } | |||||
| this._mouseUpHandle = () => { | |||||
| this._rotateMouseUpFunction() | |||||
| } | |||||
| document.removeEventListener('mousemove', this._mouseMoveHandle, false) | |||||
| document.removeEventListener('mouseup', this._mouseUpHandle, false) | |||||
| this._rotateInitialCursorAngle = Math.atan2(-vector.y, vector.x) | |||||
| if (this._viewer.delegate.trackedEntity) { | |||||
| this._rotateFrame = undefined | |||||
| } else { | |||||
| let center = this._getCameraFocus(true) | |||||
| if ( | |||||
| !center || | |||||
| (scene.mode === Cesium.SceneMode.COLUMBUS_VIEW && | |||||
| !sscc.enableLook && | |||||
| !sscc.enableTranslate) | |||||
| ) { | |||||
| this._rotateFrame = Cesium.Transforms.eastNorthUpToFixedFrame( | |||||
| camera.positionWC, | |||||
| scene.globe.ellipsoid | |||||
| ) | |||||
| } else { | |||||
| this._rotateFrame = Cesium.Transforms.eastNorthUpToFixedFrame( | |||||
| center, | |||||
| scene.globe.ellipsoid | |||||
| ) | |||||
| } | |||||
| } | |||||
| let oldTransform | |||||
| if (this._rotateFrame) { | |||||
| oldTransform = Cesium.Matrix4.clone(camera.transform) | |||||
| camera.lookAtTransform(this._rotateFrame) | |||||
| } | |||||
| this._rotateInitialCameraAngle = -camera.heading | |||||
| if (this._rotateFrame && oldTransform) { | |||||
| camera.lookAtTransform(oldTransform) | |||||
| } | |||||
| document.addEventListener('mousemove', this._mouseMoveHandle, false) | |||||
| document.addEventListener('mouseup', this._mouseUpHandle, false) | |||||
| } | |||||
| _rotateMouseMoveFunction(e) { | |||||
| let camera = this._viewer.camera | |||||
| let vector = this._getVector(e) | |||||
| let angle = Math.atan2(-vector.y, vector.x) | |||||
| let angleDifference = angle - this._rotateInitialCursorAngle | |||||
| let newCameraAngle = Cesium.Math.zeroToTwoPi( | |||||
| this._rotateInitialCameraAngle - angleDifference | |||||
| ) | |||||
| let oldTransform | |||||
| if (this._rotateFrame) { | |||||
| oldTransform = Cesium.Matrix4.clone(camera.transform) | |||||
| camera.lookAtTransform(this._rotateFrame) | |||||
| } | |||||
| let currentCameraAngle = -camera.heading | |||||
| camera.rotateRight(newCameraAngle - currentCameraAngle) | |||||
| if (this._rotateFrame && oldTransform) { | |||||
| camera.lookAtTransform(oldTransform) | |||||
| } | |||||
| } | |||||
| _rotateMouseUpFunction() { | |||||
| document.removeEventListener('mousemove', this._mouseMoveHandle, false) | |||||
| document.removeEventListener('mouseup', this._mouseUpHandle, false) | |||||
| this._mouseMoveHandle = undefined | |||||
| this._mouseUpHandle = undefined | |||||
| } | |||||
| _getVector(e) { | |||||
| let compassRectangle = this._compassRectangle | |||||
| let center = new Cesium.Cartesian2( | |||||
| (compassRectangle.right - compassRectangle.left) / 2.0, | |||||
| (compassRectangle.bottom - compassRectangle.top) / 2.0 | |||||
| ) | |||||
| let clickLocation = new Cesium.Cartesian2( | |||||
| e.clientX - compassRectangle.left, | |||||
| e.clientY - compassRectangle.top | |||||
| ) | |||||
| let vector = new Cesium.Cartesian2() | |||||
| Cesium.Cartesian2.subtract(clickLocation, center, vector) | |||||
| return vector | |||||
| } | |||||
| } | |||||
| Widget.registerType('compass') | |||||
| export default Compass |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2019-12-31 17:32:01 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| class ContextMenu extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-context-menu') | |||||
| this._ulEl = undefined | |||||
| this._handler = undefined | |||||
| this._overlay = undefined | |||||
| this._position = undefined | |||||
| this._wgs84Position = undefined | |||||
| this._surfacePosition = undefined | |||||
| this._wgs84SurfacePosition = undefined | |||||
| this._windowPosition = undefined | |||||
| this._config = {} | |||||
| this._defaultMenu = [ | |||||
| { | |||||
| label: '飞到默认位置', | |||||
| callback: e => { | |||||
| this._viewer.camera.flyHome(1.5) | |||||
| }, | |||||
| context: this | |||||
| }, | |||||
| { | |||||
| label: '取消飞行', | |||||
| callback: e => { | |||||
| this._viewer.camera.cancelFlight() | |||||
| }, | |||||
| context: this | |||||
| } | |||||
| ] | |||||
| this._overlayMenu = [] | |||||
| this.type = Widget.getWidgetType('contextmenu') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| set DEFAULT_MENU(menus) { | |||||
| this._defaultMenu = menus | |||||
| return this | |||||
| } | |||||
| set config(config) { | |||||
| this._config = config | |||||
| config.customClass && this._setCustomClass() | |||||
| return this | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'contextMenu', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| this._handler = new Cesium.ScreenSpaceEventHandler(this._viewer.canvas) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| this._handler.setInputAction(movement => { | |||||
| this._onRightClick(movement) | |||||
| }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) | |||||
| this._handler.setInputAction(movement => { | |||||
| this._onClick(movement) | |||||
| }, Cesium.ScreenSpaceEventType.LEFT_CLICK) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() { | |||||
| this._handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK) | |||||
| this._handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| this._ulEl = DomUtil.create('ul', 'menu-list', this._wrapper) | |||||
| this._ready = true | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountMenu() { | |||||
| while (this._ulEl.hasChildNodes()) { | |||||
| this._ulEl.removeChild(this._ulEl.firstChild) | |||||
| } | |||||
| // Add menu item | |||||
| if (this._overlayMenu && this._overlayMenu.length) { | |||||
| this._overlayMenu.forEach(item => { | |||||
| this._addMenuItem(item.label, item.callback, item.context || this) | |||||
| }) | |||||
| } | |||||
| if (this._defaultMenu && this._defaultMenu.length) { | |||||
| this._defaultMenu.forEach(item => { | |||||
| this._addMenuItem(item.label, item.callback, item.context || this) | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param movement | |||||
| * @private | |||||
| */ | |||||
| _onRightClick(movement) { | |||||
| if (!this._enable) { | |||||
| return | |||||
| } | |||||
| this._overlay = undefined | |||||
| let scene = this._viewer.scene | |||||
| this._windowPosition = movement.position | |||||
| this._updateWindowCoord(movement.position) | |||||
| let target = scene.pick(movement.position) | |||||
| if (scene.pickPositionSupported) { | |||||
| this._position = scene.pickPosition(movement.position) | |||||
| } | |||||
| if (this._position) { | |||||
| let c = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this._position) | |||||
| if (c) { | |||||
| this._wgs84Position = { | |||||
| lng: Cesium.Math.toDegrees(c.longitude), | |||||
| lat: Cesium.Math.toDegrees(c.latitude), | |||||
| alt: c.height | |||||
| } | |||||
| } | |||||
| } | |||||
| if (scene.mode === Cesium.SceneMode.SCENE3D) { | |||||
| let ray = scene.camera.getPickRay(movement.position) | |||||
| this._surfacePosition = scene.globe.pick(ray, scene) | |||||
| } else { | |||||
| this._surfacePosition = scene.camera.pickEllipsoid( | |||||
| movement.position, | |||||
| Cesium.Ellipsoid.WGS84 | |||||
| ) | |||||
| } | |||||
| if (this._surfacePosition) { | |||||
| let c = Cesium.Ellipsoid.WGS84.cartesianToCartographic( | |||||
| this._surfacePosition | |||||
| ) | |||||
| if (c) { | |||||
| this._wgs84SurfacePosition = { | |||||
| lng: Cesium.Math.toDegrees(c.longitude), | |||||
| lat: Cesium.Math.toDegrees(c.latitude), | |||||
| alt: c.height | |||||
| } | |||||
| } | |||||
| } | |||||
| // for Entity | |||||
| if (target && target.id && target.id instanceof Cesium.Entity) { | |||||
| let layer = this._viewer | |||||
| .getLayers() | |||||
| .filter(item => item.layerId === target.id.layerId)[0] | |||||
| if (layer && layer.getOverlay) { | |||||
| this._overlay = layer.getOverlay(target.id.overlayId) | |||||
| } | |||||
| } | |||||
| // for Cesium3DTileFeature | |||||
| if (target && target instanceof Cesium.Cesium3DTileFeature) { | |||||
| let layer = this._viewer | |||||
| .getLayers() | |||||
| .filter(item => item.layerId === target.tileset.layerId)[0] | |||||
| if (layer && layer.getOverlay) { | |||||
| this._overlay = layer.getOverlay(target.tileset.overlayId) | |||||
| } | |||||
| } | |||||
| this._overlayMenu = this._overlay?.contextMenu || [] | |||||
| this._mountMenu() | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param movement | |||||
| * @private | |||||
| */ | |||||
| _onClick(movement) { | |||||
| this.hide() | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param windowCoord | |||||
| * @private | |||||
| */ | |||||
| _updateWindowCoord(windowCoord) { | |||||
| this._wrapper.style.cssText = ` | |||||
| visibility:visible; | |||||
| z-index:1; | |||||
| transform:translate3d(${Math.round(windowCoord.x)}px,${Math.round( | |||||
| windowCoord.y | |||||
| )}px, 0); | |||||
| ` | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _setCustomClass() { | |||||
| DomUtil.setClass( | |||||
| this._wrapper, | |||||
| `dc-context-menu ${this._config.customClass}` | |||||
| ) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param label | |||||
| * @param method | |||||
| * @param context | |||||
| * @returns {ContextMenu} | |||||
| * @private | |||||
| */ | |||||
| _addMenuItem(label, method, context) { | |||||
| if (!label || !method) { | |||||
| return this | |||||
| } | |||||
| let menu = DomUtil.create('li', 'menu-item', null) | |||||
| let a = DomUtil.create('a', '', menu) | |||||
| a.innerHTML = label | |||||
| a.href = 'javascript:void(0)' | |||||
| let self = this | |||||
| if (method) { | |||||
| a.onclick = () => { | |||||
| method.call(context, { | |||||
| windowPosition: self._windowPosition, | |||||
| position: self._position, | |||||
| wgs84Position: self._wgs84Position, | |||||
| surfacePosition: self._surfacePosition, | |||||
| wgs84SurfacePosition: self._wgs84SurfacePosition, | |||||
| overlay: self._overlay | |||||
| }) | |||||
| self.hide() | |||||
| } | |||||
| } | |||||
| this._ulEl.appendChild(menu) | |||||
| return this | |||||
| } | |||||
| } | |||||
| Widget.registerType('contextmenu') | |||||
| export default ContextMenu |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-12-09 20:54:06 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import { SceneEventType } from '@dc-modules/event' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| const geodesic = new Cesium.EllipsoidGeodesic() | |||||
| const BASE = [1, 2, 3, 5] | |||||
| const DIS = [ | |||||
| ...BASE, | |||||
| ...BASE.map(item => item * 10), | |||||
| ...BASE.map(item => item * 100), | |||||
| ...BASE.map(item => item * 1000), | |||||
| ...BASE.map(item => item * 10000), | |||||
| ...BASE.map(item => item * 100000), | |||||
| ...BASE.map(item => item * 1000000) | |||||
| ] | |||||
| class DistanceLegend extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-distance-legend') | |||||
| this._labelEl = undefined | |||||
| this._scaleBarEl = undefined | |||||
| this._lastUpdate = Cesium.getTimestamp() | |||||
| this.type = Widget.getWidgetType('distance_legend') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'distanceLegend', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| this._viewer.on(SceneEventType.POST_RENDER, this._updateContent, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() { | |||||
| this._viewer.off(SceneEventType.POST_RENDER, this._updateContent, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param scene | |||||
| * @param time | |||||
| * @returns | |||||
| * @private | |||||
| */ | |||||
| _updateContent(scene, time) { | |||||
| let now = Cesium.getTimestamp() | |||||
| if (now < this._lastUpdate + 250) { | |||||
| return | |||||
| } | |||||
| if (!this._labelEl || !this._scaleBarEl) { | |||||
| return | |||||
| } | |||||
| this._lastUpdate = now | |||||
| let width = scene.canvas.width | |||||
| let height = scene.canvas.height | |||||
| let left = scene.camera.getPickRay( | |||||
| new Cesium.Cartesian2((width / 2) | 0, height - 1) | |||||
| ) | |||||
| let right = scene.camera.getPickRay( | |||||
| new Cesium.Cartesian2((1 + width / 2) | 0, height - 1) | |||||
| ) | |||||
| let leftPosition = scene.globe.pick(left, scene) | |||||
| let rightPosition = scene.globe.pick(right, scene) | |||||
| if (!leftPosition || !rightPosition) { | |||||
| return | |||||
| } | |||||
| geodesic.setEndPoints( | |||||
| scene.globe.ellipsoid.cartesianToCartographic(leftPosition), | |||||
| scene.globe.ellipsoid.cartesianToCartographic(rightPosition) | |||||
| ) | |||||
| let pixelDistance = geodesic.surfaceDistance | |||||
| let maxBarWidth = 100 | |||||
| let distance = 0 | |||||
| for (let i = DIS.length - 1; i >= 0; --i) { | |||||
| if (DIS[i] / pixelDistance < maxBarWidth) { | |||||
| distance = DIS[i] | |||||
| break | |||||
| } | |||||
| } | |||||
| if (distance) { | |||||
| this._wrapper.style.visibility = 'visible' | |||||
| this._labelEl.innerHTML = | |||||
| distance >= 1000 ? `${distance / 1000} km` : `${distance} m` | |||||
| let barWidth = (distance / pixelDistance) | 0 | |||||
| this._scaleBarEl.style.cssText = `width: ${barWidth}px; left: ${(125 - | |||||
| barWidth) / | |||||
| 2}px;` | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| this._labelEl = DomUtil.create('div', 'label', this._wrapper) | |||||
| this._scaleBarEl = DomUtil.create('div', 'scale-bar', this._wrapper) | |||||
| this._wrapper.style.visibility = 'hidden' | |||||
| this._ready = true | |||||
| } | |||||
| } | |||||
| Widget.registerType('distance_legend') | |||||
| export default DistanceLegend |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-03-15 17:47:42 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { Util, DomUtil } from '@dc-modules/utils' | |||||
| import { SceneEventType } from '@dc-modules/event' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| const DEF_OPTS = { | |||||
| animation: false, | |||||
| baseLayerPicker: false, | |||||
| imageryProvider: false, | |||||
| fullscreenButton: false, | |||||
| geocoder: false, | |||||
| homeButton: false, | |||||
| infoBox: false, | |||||
| sceneModePicker: false, | |||||
| selectionIndicator: false, | |||||
| timeline: false, | |||||
| navigationHelpButton: false, | |||||
| navigationInstructionsInitiallyVisible: false, | |||||
| creditContainer: undefined | |||||
| } | |||||
| class HawkeyeMap extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-hawkeye-map', null) | |||||
| this._wrapper.setAttribute('id', Util.uuid()) | |||||
| this._baseLayers = [] | |||||
| this._map = undefined | |||||
| this.type = Widget.getWidgetType('hawkeye_map') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| get baseLayers() { | |||||
| return this._baseLayers | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| let map = new Cesium.Viewer(this._wrapper, { | |||||
| ...DEF_OPTS, | |||||
| sceneMode: Cesium.SceneMode.SCENE2D | |||||
| }) | |||||
| map.imageryLayers.removeAll() | |||||
| map.cesiumWidget.creditContainer.style.display = 'none' | |||||
| map.cesiumWidget.screenSpaceEventHandler.removeInputAction( | |||||
| Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK | |||||
| ) | |||||
| map.scene.backgroundColor = Cesium.Color.TRANSPARENT | |||||
| Util.merge(map.scene.screenSpaceCameraController, { | |||||
| enableRotate: false, | |||||
| enableTranslate: false, | |||||
| enableZoom: false, | |||||
| enableTilt: false, | |||||
| enableLook: false, | |||||
| maximumZoomDistance: 40489014.0 | |||||
| }) | |||||
| this._map = map | |||||
| this._ready = true | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| this._viewer.on(SceneEventType.CAMERA_CHANGED, this._syncMap, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() { | |||||
| this._viewer.off(SceneEventType.CAMERA_CHANGED, this._syncMap, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'hawkeyeMap', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| this._viewer.camera.percentageChanged = 0.01 | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @returns {boolean} | |||||
| * @private | |||||
| */ | |||||
| _syncMap() { | |||||
| let viewCenter = new Cesium.Cartesian2( | |||||
| Math.floor(this._viewer.canvas.clientWidth / 2), | |||||
| Math.floor(this._viewer.canvas.clientHeight / 2) | |||||
| ) | |||||
| let worldPosition = this._viewer.scene.camera.pickEllipsoid(viewCenter) | |||||
| if (!worldPosition) { | |||||
| return false | |||||
| } | |||||
| let distance = Cesium.Cartesian3.distance( | |||||
| worldPosition, | |||||
| this._viewer.scene.camera.positionWC | |||||
| ) | |||||
| this._map.scene.camera.lookAt( | |||||
| worldPosition, | |||||
| new Cesium.Cartesian3(0.0, 0.0, distance) | |||||
| ) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param baseLayer | |||||
| * @returns {HawkeyeMap} | |||||
| */ | |||||
| addBaseLayer(baseLayer) { | |||||
| if (!this._map || !this._enable) { | |||||
| return this | |||||
| } | |||||
| if (baseLayer) { | |||||
| if (this._baseLayers && this._baseLayers.length) { | |||||
| this._map.imageryLayers.removeAll() | |||||
| } | |||||
| if (!Array.isArray(baseLayer)) { | |||||
| baseLayer = [baseLayer] | |||||
| } | |||||
| baseLayer.forEach(item => { | |||||
| this._baseLayers.push(this._map.imageryLayers.addImageryProvider(item)) | |||||
| }) | |||||
| } | |||||
| return this | |||||
| } | |||||
| } | |||||
| Widget.registerType('hawkeye_map') | |||||
| export default HawkeyeMap |
| /** | |||||
| * @Author: Liquid | |||||
| * @Date: 2021-03-02 13:38:48 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| class LoadingMask extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-loading-mask') | |||||
| this.type = Widget.getWidgetType('loading_mask') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'loadingMask', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| let el = DomUtil.parseDom( | |||||
| ` | |||||
| <span></span> | |||||
| <span></span> | |||||
| <span></span> | |||||
| <span></span> | |||||
| <span></span> | |||||
| `, | |||||
| true, | |||||
| 'loading' | |||||
| ) | |||||
| this._wrapper.appendChild(el) | |||||
| this._ready = true | |||||
| } | |||||
| } | |||||
| Widget.registerType('loading_mask') | |||||
| export default LoadingMask |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-03-04 18:02:32 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import { MouseEventType, SceneEventType } from '@dc-modules/event' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| class LocationBar extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-location-bar') | |||||
| this._mouseEl = undefined | |||||
| this._cameraEl = undefined | |||||
| this.type = Widget.getWidgetType('location_bar') | |||||
| this._state = State.INITIALIZED | |||||
| this._lastUpdate = Cesium.getTimestamp() | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'locationBar', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| this._viewer.on(MouseEventType.MOUSE_MOVE, this._moveHandler, this) | |||||
| this._viewer.on(SceneEventType.CAMERA_CHANGED, this._cameraHandler, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() { | |||||
| this._viewer.off(MouseEventType.MOUSE_MOVE, this._moveHandler, this) | |||||
| this._viewer.off(SceneEventType.CAMERA_CHANGED, this._cameraHandler, this) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| this._mouseEl = DomUtil.create('div', 'mouse-location', this._wrapper) | |||||
| this._cameraEl = DomUtil.create('div', 'camera-location', this._wrapper) | |||||
| this._ready = true | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param e | |||||
| * @private | |||||
| */ | |||||
| _moveHandler(e) { | |||||
| let now = Cesium.getTimestamp() | |||||
| if (now < this._lastUpdate + 300) { | |||||
| return | |||||
| } | |||||
| this._lastUpdate = now | |||||
| let ellipsoid = Cesium.Ellipsoid.WGS84 | |||||
| let cartographic = e.surfacePosition | |||||
| ? ellipsoid.cartesianToCartographic(e.surfacePosition) | |||||
| : undefined | |||||
| let lng = +Cesium.Math.toDegrees(cartographic?.longitude || 0) | |||||
| let lat = +Cesium.Math.toDegrees(cartographic?.latitude || 0) | |||||
| let alt = cartographic | |||||
| ? +this._viewer.scene.globe.getHeight(cartographic) | |||||
| : 0 | |||||
| this._mouseEl.innerHTML = ` | |||||
| <span>经度:${lng.toFixed(8)}</span> | |||||
| <span>纬度:${lat.toFixed(8)}</span> | |||||
| <span>海拔:${alt.toFixed(2)} 米</span>` | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _cameraHandler() { | |||||
| let now = Cesium.getTimestamp() | |||||
| if (now < this._lastUpdate + 300) { | |||||
| return | |||||
| } | |||||
| this._lastUpdate = now | |||||
| let cameraPosition = this._viewer.cameraPosition | |||||
| this._cameraEl.innerHTML = ` | |||||
| <span>视角:${(+cameraPosition.pitch).toFixed(2)}</span> | |||||
| <span>视高:${(+cameraPosition.alt).toFixed(2)} 米</span> | |||||
| ` | |||||
| } | |||||
| } | |||||
| Widget.registerType('location_bar') | |||||
| export default LocationBar |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-03-04 15:38:40 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import Icons from '@dc-modules/icons' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| class MapSplit extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-slider') | |||||
| this._baseLayer = undefined | |||||
| this._moveActive = false | |||||
| this.type = Widget.getWidgetType('map_split') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'mapSplit', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| this._viewer.scene.imagerySplitPosition = 0.5 | |||||
| this._wrapper.style.left = '50%' | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _unbindEvent() { | |||||
| if (this._baseLayer) { | |||||
| this._viewer.scene.imagerySplitPosition = | |||||
| this._baseLayer.splitDirection > 0 ? 1 : 0 | |||||
| } else { | |||||
| this._viewer.scene.imagerySplitPosition = 0 | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| let splitter = DomUtil.parseDom(Icons.splitter, true, 'splitter') | |||||
| this._wrapper.appendChild(splitter) | |||||
| let handler = new Cesium.ScreenSpaceEventHandler(splitter) | |||||
| let self = this | |||||
| handler.setInputAction(() => { | |||||
| self._moveActive = true | |||||
| }, Cesium.ScreenSpaceEventType.LEFT_DOWN) | |||||
| handler.setInputAction(() => { | |||||
| self._moveActive = true | |||||
| }, Cesium.ScreenSpaceEventType.PINCH_START) | |||||
| handler.setInputAction(movement => { | |||||
| self._moveHandler(movement) | |||||
| }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) | |||||
| handler.setInputAction(movement => { | |||||
| self._moveHandler(movement) | |||||
| }, Cesium.ScreenSpaceEventType.PINCH_MOVE) | |||||
| handler.setInputAction(() => { | |||||
| self._moveActive = false | |||||
| }, Cesium.ScreenSpaceEventType.LEFT_UP) | |||||
| handler.setInputAction(() => { | |||||
| self._moveActive = false | |||||
| }, Cesium.ScreenSpaceEventType.PINCH_END) | |||||
| this._ready = true | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param movement | |||||
| * @private | |||||
| */ | |||||
| _moveHandler(movement) { | |||||
| if (!this._moveActive || !this._enable) { | |||||
| return | |||||
| } | |||||
| let relativeOffset = movement.endPosition.x | |||||
| let splitPosition = | |||||
| (this._wrapper.offsetLeft + relativeOffset) / | |||||
| this._wrapper.parentElement.offsetWidth | |||||
| this._wrapper.style.left = 100.0 * splitPosition + '%' | |||||
| this._viewer.scene.imagerySplitPosition = splitPosition | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param baseLayer | |||||
| * @param splitDirection | |||||
| * @returns {MapSplit} | |||||
| */ | |||||
| addBaseLayer(baseLayer, splitDirection = 1) { | |||||
| if (!this._viewer || !this._enable) { | |||||
| return this | |||||
| } | |||||
| if (baseLayer) { | |||||
| this._baseLayer && this._viewer.imageryLayers.remove(this._baseLayer) | |||||
| this._baseLayer = this._viewer.imageryLayers.addImageryProvider(baseLayer) | |||||
| this._baseLayer.splitDirection = splitDirection || 0 | |||||
| this._viewer.scene.imagerySplitPosition = | |||||
| this._wrapper.offsetLeft / this._wrapper.parentElement.offsetWidth | |||||
| } | |||||
| return this | |||||
| } | |||||
| } | |||||
| Widget.registerType('map_split') | |||||
| export default MapSplit |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-02-11 18:34:46 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| class MapSwitch extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-map-switch') | |||||
| this._config = undefined | |||||
| this._cache = [] | |||||
| this.type = Widget.getWidgetType('map_switch') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * Override the superclass function | |||||
| * @private | |||||
| */ | |||||
| _enableHook() { | |||||
| !this._wrapper.parentNode && | |||||
| this._viewer && | |||||
| this._viewer.dcContainer.appendChild(this._wrapper) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'mapSwitch', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| this.enable = true | |||||
| let self = this | |||||
| this._wrapper.onmouseover = () => { | |||||
| let width = 80 | |||||
| if (self._cache.length > 0) { | |||||
| width = self._cache.length * 85 | |||||
| } | |||||
| this._wrapper.style.width = `${width}px` | |||||
| } | |||||
| this._wrapper.onmouseout = () => { | |||||
| self._wrapper.style.width = `80px` | |||||
| } | |||||
| } | |||||
| _addItem(map) { | |||||
| let mapEl = DomUtil.create('div', 'map-item', this._wrapper) | |||||
| let index = this._cache.length ? this._cache.length - 1 : 0 | |||||
| index === 0 && DomUtil.addClass(mapEl, 'active') | |||||
| mapEl.setAttribute('data-index', String(index)) | |||||
| mapEl.onclick = e => { | |||||
| let old = document.getElementsByClassName('map-item active') | |||||
| if (old && old.length) { | |||||
| old[0].className = 'map-item' | |||||
| } | |||||
| if (this._viewer) { | |||||
| e.target.className = 'map-item active' | |||||
| this._viewer.changeBaseLayer(+e.target.getAttribute('data-index') || 0) | |||||
| } | |||||
| } | |||||
| if (map.iconUrl) { | |||||
| mapEl.style.cssText = ` | |||||
| background:url(${map.iconUrl}); | |||||
| ` | |||||
| } | |||||
| let span = DomUtil.create('span', '', mapEl) | |||||
| span.innerHTML = map.name || '地图' | |||||
| } | |||||
| /** | |||||
| * add map | |||||
| * @param map | |||||
| */ | |||||
| addMap(map = {}) { | |||||
| if (this._enable) { | |||||
| this._cache.push(map) | |||||
| this._addItem(map) | |||||
| if (this._cache.length > 1) { | |||||
| this._wrapper.style.visibility = 'visible' | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| Widget.registerType('map_switch') | |||||
| export default MapSwitch |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-01-15 19:16:45 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| class Popup extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-popup') | |||||
| this._config = { customClass: '' } | |||||
| this._position = undefined | |||||
| this.type = Widget.getWidgetType('popup') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| set config(config) { | |||||
| this._config = config | |||||
| config.customClass && this._setCustomClass() | |||||
| } | |||||
| /** | |||||
| * binds event | |||||
| * @private | |||||
| */ | |||||
| _bindEvent() { | |||||
| if (this._viewer && this._wrapper) { | |||||
| let self = this | |||||
| let scene = this._viewer.scene | |||||
| scene.postRender.addEventListener(() => { | |||||
| if ( | |||||
| self._position && | |||||
| self._enable && | |||||
| self._updateWindowCoord && | |||||
| self._wrapper.style.visibility === 'visible' | |||||
| ) { | |||||
| let windowCoord = Cesium.SceneTransforms.wgs84ToWindowCoordinates( | |||||
| scene, | |||||
| self._position | |||||
| ) | |||||
| windowCoord && self._updateWindowCoord(windowCoord) | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| this._wrapper.style.visibility = 'hidden' | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| this.enable = true | |||||
| this._bindEvent() | |||||
| Object.defineProperty(this._viewer, 'popup', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param windowCoord | |||||
| * @private | |||||
| */ | |||||
| _updateWindowCoord(windowCoord) { | |||||
| let x = windowCoord.x - this._wrapper.offsetWidth / 2 | |||||
| let y = windowCoord.y - this._wrapper.offsetHeight | |||||
| if (this._config && this._config.position === 'left') { | |||||
| x = windowCoord.x - this._wrapper.offsetWidth | |||||
| } else if (this._config && this._config.position === 'right') { | |||||
| x = windowCoord.x | |||||
| } | |||||
| this._wrapper.style.cssText = ` | |||||
| visibility:visible; | |||||
| z-index:1; | |||||
| transform:translate3d(${Math.round(x)}px,${Math.round(y)}px, 0); | |||||
| ` | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _setCustomClass() { | |||||
| DomUtil.setClass(this._wrapper, `dc-popup ${this._config.customClass}`) | |||||
| } | |||||
| /** | |||||
| * Setting wrapper | |||||
| * @param wrapper | |||||
| * @returns {Widget} | |||||
| */ | |||||
| setWrapper(wrapper) { | |||||
| if (wrapper && wrapper instanceof Element) { | |||||
| this._wrapper = wrapper | |||||
| DomUtil.addClass(this._wrapper, 'dc-popup') | |||||
| } | |||||
| return this | |||||
| } | |||||
| /** | |||||
| * | |||||
| * Setting widget position | |||||
| * @param {*} position | |||||
| * | |||||
| */ | |||||
| setPosition(position) { | |||||
| this._position = position | |||||
| this._wrapper && | |||||
| (this._wrapper.style.cssText = ` | |||||
| visibility:visible; | |||||
| `) | |||||
| return this | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param {*} position | |||||
| * @param {*} content | |||||
| */ | |||||
| showAt(position, content) { | |||||
| this.setPosition(position).setContent(content) | |||||
| return this | |||||
| } | |||||
| } | |||||
| Widget.registerType('popup') | |||||
| export default Popup |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-02-01 12:07:54 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| class Tooltip extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-tool-tip') | |||||
| this._ready = true | |||||
| this.type = Widget.getWidgetType('tooltip') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'tooltip', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param {*} windowCoord | |||||
| * | |||||
| */ | |||||
| _updateWindowCoord(windowCoord) { | |||||
| let x = windowCoord.x + 10 | |||||
| let y = windowCoord.y - this._wrapper.offsetHeight / 2 | |||||
| this._wrapper.style.cssText = ` | |||||
| visibility:visible; | |||||
| z-index:1; | |||||
| transform:translate3d(${Math.round(x)}px,${Math.round(y)}px, 0); | |||||
| ` | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param {*} position | |||||
| * @param {*} content | |||||
| * | |||||
| */ | |||||
| showAt(position, content) { | |||||
| if (!this._enable) { | |||||
| return this | |||||
| } | |||||
| position && this._updateWindowCoord(position) | |||||
| this.setContent(content) | |||||
| return this | |||||
| } | |||||
| } | |||||
| Widget.registerType('tooltip') | |||||
| export default Tooltip |
| /** | |||||
| * @Author: Caven | |||||
| * @Date: 2020-05-06 13:25:36 | |||||
| */ | |||||
| import State from '@dc-modules/state/State' | |||||
| import Icons from '@dc-modules/icons' | |||||
| import { DomUtil } from '@dc-modules/utils' | |||||
| import Widget from '../Widget' | |||||
| const { Cesium } = DC.Namespace | |||||
| class ZoomController extends Widget { | |||||
| constructor() { | |||||
| super() | |||||
| this._wrapper = DomUtil.create('div', 'dc-zoom-controller') | |||||
| this._zoomInEl = undefined | |||||
| this._zoomOutEl = undefined | |||||
| this._refreshEl = undefined | |||||
| this.type = Widget.getWidgetType('zoom_controller') | |||||
| this._state = State.INITIALIZED | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param scene | |||||
| * @returns {Cartesian3} | |||||
| * @private | |||||
| */ | |||||
| _getCameraFocus(scene) { | |||||
| const ray = new Cesium.Ray( | |||||
| scene.camera.positionWC, | |||||
| scene.camera.directionWC | |||||
| ) | |||||
| const intersections = Cesium.IntersectionTests.rayEllipsoid( | |||||
| ray, | |||||
| Cesium.Ellipsoid.WGS84 | |||||
| ) | |||||
| if (intersections) { | |||||
| return Cesium.Ray.getPoint(ray, intersections.start) | |||||
| } | |||||
| // Camera direction is not pointing at the globe, so use the ellipsoid horizon point as | |||||
| // the focal point. | |||||
| return Cesium.IntersectionTests.grazingAltitudeLocation( | |||||
| ray, | |||||
| Cesium.Ellipsoid.WGS84 | |||||
| ) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @param camera | |||||
| * @param focus | |||||
| * @param scalar | |||||
| * @returns {Cartesian3} | |||||
| * @private | |||||
| */ | |||||
| _getCameraPosition(camera, focus, scalar) { | |||||
| const cartesian3Scratch = new Cesium.Cartesian3() | |||||
| let direction = Cesium.Cartesian3.subtract( | |||||
| focus, | |||||
| camera.position, | |||||
| cartesian3Scratch | |||||
| ) | |||||
| let movementVector = Cesium.Cartesian3.multiplyByScalar( | |||||
| direction, | |||||
| scalar, | |||||
| cartesian3Scratch | |||||
| ) | |||||
| return Cesium.Cartesian3.add( | |||||
| camera.position, | |||||
| movementVector, | |||||
| cartesian3Scratch | |||||
| ) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @returns {boolean} | |||||
| * @private | |||||
| */ | |||||
| _zoomIn() { | |||||
| let scene = this._viewer.scene | |||||
| let camera = scene.camera | |||||
| let sscc = scene.screenSpaceCameraController | |||||
| if ( | |||||
| scene.mode === Cesium.SceneMode.MORPHING || | |||||
| !sscc.enableInputs || | |||||
| scene.mode === Cesium.SceneMode.COLUMBUS_VIEW | |||||
| ) { | |||||
| return true | |||||
| } else if (scene.mode === Cesium.SceneMode.SCENE2D) { | |||||
| camera.zoomIn(camera.positionCartographic.height * 0.5) | |||||
| } else if (scene.mode === Cesium.SceneMode.SCENE3D) { | |||||
| let focus = this._getCameraFocus(scene) | |||||
| let cameraPosition = this._getCameraPosition(camera, focus, 1 / 2) | |||||
| camera.flyTo({ | |||||
| destination: cameraPosition, | |||||
| orientation: { | |||||
| heading: camera.heading, | |||||
| pitch: camera.pitch, | |||||
| roll: camera.roll | |||||
| }, | |||||
| duration: 0.5, | |||||
| convert: false | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _refresh() { | |||||
| this._viewer.camera.flyHome(1.5) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @returns {boolean} | |||||
| * @private | |||||
| */ | |||||
| _zoomOut() { | |||||
| let scene = this._viewer.scene | |||||
| let camera = scene.camera | |||||
| let sscc = scene.screenSpaceCameraController | |||||
| if ( | |||||
| scene.mode === Cesium.SceneMode.MORPHING || | |||||
| !sscc.enableInputs || | |||||
| scene.mode === Cesium.SceneMode.COLUMBUS_VIEW | |||||
| ) { | |||||
| return true | |||||
| } else if (scene.mode === Cesium.SceneMode.SCENE2D) { | |||||
| camera.zoomOut(camera.positionCartographic.height) | |||||
| } else if (scene.mode === Cesium.SceneMode.SCENE3D) { | |||||
| let focus = this._getCameraFocus(scene) | |||||
| let cameraPosition = this._getCameraPosition(camera, focus, -1) | |||||
| camera.flyTo({ | |||||
| destination: cameraPosition, | |||||
| orientation: { | |||||
| heading: camera.heading, | |||||
| pitch: camera.pitch, | |||||
| roll: camera.roll | |||||
| }, | |||||
| duration: 0.5, | |||||
| convert: false | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _installHook() { | |||||
| Object.defineProperty(this._viewer, 'zoomController', { | |||||
| value: this, | |||||
| writable: false | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @private | |||||
| */ | |||||
| _mountContent() { | |||||
| this._zoomInEl = DomUtil.parseDom(Icons.increase, true, 'zoom-in') | |||||
| this._refreshEl = DomUtil.parseDom(Icons.refresh, true, 'refresh') | |||||
| this._zoomOutEl = DomUtil.parseDom(Icons.decrease, true, 'zoom-out') | |||||
| this._wrapper.appendChild(this._zoomInEl) | |||||
| this._wrapper.appendChild(this._refreshEl) | |||||
| this._wrapper.appendChild(this._zoomOutEl) | |||||
| let self = this | |||||
| this._zoomInEl.onclick = e => { | |||||
| self._zoomIn() | |||||
| } | |||||
| this._refreshEl.onclick = e => { | |||||
| self._refresh() | |||||
| } | |||||
| this._zoomOutEl.onclick = e => { | |||||
| self._zoomOut() | |||||
| } | |||||
| this._ready = true | |||||
| } | |||||
| } | |||||
| Widget.registerType('zoom_controller') | |||||
| export default ZoomController |