@@ -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 |