前言
Cesium入门开发系列知识点了解
Cesium api 文档介绍 详细介绍cesium每个类的函数以及属性等等 Cesium 在线例子
内容概览
- cesium结合leaflet实现鹰眼图
- cesium结合自身api 实现鹰眼图
- 源代码
Cesium结合leaflet实现鹰眼图
核心代码:通过监听cesium视图变化事件联动leaflet视图同步,同时也监听leaflet视图变化事件联动cesium视图同步
在Cesium窗口中添加小地图组件
<template>
<div style="width: 100%; height: 100%">
<div style="position: relative; width: 100%; height: 100%" ref="coreViewer">
<div ref="viewer" style="width: 100%;height:100%" id="viewer"></div>
<leafletMini :center="minimapCenter" :marker="minimapCursor" :zoom="minimapZoom" :viewRect="minimapViewRect"/>
</div>
</div>
</template>
<script>
import bindMinimap from '../scripts/eagleEye'
import leafletMini from '../components/leafletMini.vue'
import {
LMap,
LTileLayer,
LMarker,
LPopup
} from 'vue2-leaflet'
export default {
name: "cesiumView",
components: {
'leafletMini': leafletMini
},
mounted() {
this.$nextTick(() => {
const viewer = initViewer(this.$refs.viewer)
this.freezedViewer = Object.freeze({viewer})
var that = this
document.addEventListener(Cesium.Fullscreen.changeEventName, () => {
that.isFullscreen = Cesium.Fullscreen.fullscreen
})
})
},
data() {
return {
freezedViewer: undefined,
minimapCenter: undefined,
mizimapZoom: 2,
minimapCrusor: L.latlng(0.0, 0.0),
minimapViewRect: []
}
},
methods: {
bindEagleEyeOnMinimap() {
let h = parseInt(window.getComputedStyle(this.$refs.coreViewer).height)
let w = parseInt(window.getComputedStyle(this.$refs.coreViewer).width)
bindMinimap(this.freezedViewer && this.freezedViewer.viewer,(x,y,zoom,viewRectCoords)=>{
this.minimapCenter=L.latLng(y, x);
this.minimapZoom=zoom;
this.minimapCrusor=L.latLng(y, x);
this.minimapViewRect=viewRectCoords;
},w,h);
}
}
}
</script>
实现联动的代码:eagleEyle.js
import * as Cesium from 'cesium'
//启动鹰眼功能
function bindMinimap(cesiumViewer, funcWithCursorPos,windowWidth,windowHeight) {
var handler = new Cesium.ScreenSpaceEventHandler(cesiumViewer.scene.canvas);
handler.setInputAction(function(movement) {
let dynamicPosition = undefined;
let ray = cesiumViewer.camera.getPickRay(movement.endPosition);
dynamicPosition = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
let corners=getViewRect(cesiumViewer,cesiumViewer.scene.camera,windowWidth,windowHeight);
if (Cesium.defined(dynamicPosition)) {
funcWithCursorPos(Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(dynamicPosition).longitude),
Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(dynamicPosition).latitude),
getZoomLevel(cesiumViewer.scene.camera),
corners
);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
//计算相机视域
function getViewRect(cesiumViewer,camera,windowWidth,windowHeight){
let cornerPos = undefined;
let ray=undefined;
let positions=[];
ray = cesiumViewer.camera.getPickRay(new Cesium.Cartesian2(0,0));
cornerPos = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
if (!Cesium.defined(cornerPos)){
return [];
}
positions.push([Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).latitude),
Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).longitude)]);
ray = cesiumViewer.camera.getPickRay(new Cesium.Cartesian2(0,windowHeight));
cornerPos = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
if (!Cesium.defined(cornerPos)){
return [];
}
positions.push([Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).latitude),
Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).longitude)]);
ray = cesiumViewer.camera.getPickRay(new Cesium.Cartesian2(windowWidth,windowHeight));
cornerPos = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
if (!Cesium.defined(cornerPos)){
return [];
}
positions.push([Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).latitude),
Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).longitude)]);
ray = cesiumViewer.camera.getPickRay(new Cesium.Cartesian2(windowWidth,0));
cornerPos = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
if (!Cesium.defined(cornerPos)){
return [];
}
positions.push([Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).latitude),
Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cornerPos).longitude)]);
return positions
}
//计算地图缩放等级
function getZoomLevel(camera) {
let h = camera.positionCartographic.height;
if (h <= 100) { //0.01
return 19;
} else if (h <= 300) { //0.02
return 18;
} else if (h <= 660) { //0.05
return 17;
} else if (h <= 1300) { //0.1
return 16;
} else if (h <= 2600) { //0.2
return 15;
} else if (h <= 6400) { //0.5
return 14;
} else if (h <= 13200) { //1
return 13;
} else if (h <= 26000) { //2
return 12;
} else if (h <= 67985) { //5
return 11;
} else if (h <= 139780) { //10
return 10;
} else if (h <= 250600) { //20
return 9;
} else if (h <= 380000) { //30
return 8;
} else if (h <= 640000) { //50
return 7;
} else if (h <= 1280000) { //100
return 6;
} else if (h <= 2600000) { //200
return 5;
} else if (h <= 6100000) { //500
return 4;
} else if (h <= 11900000) { //1000
return 3;
} else {
return 2;
}
}
export default bindMinimap;
总结
Vue绑定数据很方便,通过Props就能把Cesium主窗口的数据绑定给miniMap子窗口,不需要写多余的代码。包括小地图的中心位置、鼠标坐标、视域范围都是这样同步过来的,且感受不到任何延迟。
Cesium 结合Cesium实现鹰眼图
import { DomUtil, Util } from '../utils'
import State from '../state/State'
import Widget from './Widget'
const { Cesium } = DC.Namespace
const DEF_OPTS = {
animation: false,
baseLayerPicker: 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._baseLayer = undefined
this._delegate = undefined
this.type = Widget.getWidgetType('hawkeye_map')
this._state = State.INITIALIZED
}
_prepareDelegate() {
this._delegate = new Cesium.Viewer(this._wrapper, {
...DEF_OPTS,
sceneMode: Cesium.SceneMode.SCENE2D
})
this._delegate.scene.screenSpaceCameraController.enableRotate = false
this._delegate.scene.screenSpaceCameraController.enableTranslate = false
this._delegate.scene.screenSpaceCameraController.enableZoom = false
this._delegate.scene.screenSpaceCameraController.enableTilt = false
this._delegate.scene.screenSpaceCameraController.enableLook = false
this._delegate.cesiumWidget._creditContainer.style.display = 'none'
this._delegate.cesiumWidget.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
)
this._delegate.scene.screenSpaceCameraController.maximumZoomDistance = 40489014.0
this._delegate.scene.backgroundColor = Cesium.Color.TRANSPARENT
this._delegate.scene.postProcessStages.fxaa.enabled = true
this._delegate.imageryLayers.removeAll()
}
_bindEvent() {
this._viewer.camera.changed.addEventListener(this._sync2DView, this)
}
_unbindEvent() {
this._viewer.camera.changed.removeEventListener(this._sync2DView, this)
}
_installHook() {
this._prepareDelegate()
this._viewer.camera.percentageChanged = 0.01
}
_sync2DView() {
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._delegate.scene.camera.lookAt(
worldPosition,
new Cesium.Cartesian3(0.0, 0.0, distance)
)
}
addBaseLayer(baseLayer) {
if (!this._delegate || !this._enable) {
return this
}
if (baseLayer) {
if (this._baseLayer) {
this._delegate.imageryLayers.remove(this._baseLayer)
}
this._baseLayer = this._delegate.imageryLayers.addImageryProvider(
baseLayer
)
}
return this
}
}
Widget.registerType('hawkeye_map')
export default HawkeyeMap