| @@ -0,0 +1,152 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,8 @@ | |||
| /** | |||
| * @Author: Caven | |||
| * @Date: 2020-05-10 10:15:46 | |||
| */ | |||
| let WidgetType = {} | |||
| export default WidgetType | |||
| @@ -0,0 +1,34 @@ | |||
| /** | |||
| * @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() | |||
| } | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,452 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,265 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,132 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,150 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,52 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,109 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,129 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,94 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,142 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,65 @@ | |||
| /** | |||
| * @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 | |||
| @@ -0,0 +1,189 @@ | |||
| /** | |||
| * @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 | |||