同步视角
// 绑定事件
function bindEvent() {
// 鹰眼与主图同步
viewer.camera.changed.addEventListener(syncEyeMap);
// 第一次刷新渲染时联动
viewer.scene.preRender.addEventListener(syncEyeMap);
// 主图与鹰眼图同步
miniViewer.camera.changed.addEventListener(syncMap);
miniViewer.scene.preRender.addEventListener(syncMap);
}
// 移除事件
function removeEvent() {
// 鹰眼与主图同步
viewer.camera.changed.removeEventListener(syncEyeMap);
// 第一次刷新渲染时联动
viewer.scene.preRender.removeEventListener(syncEyeMap);
// 主图与鹰眼图同步
miniViewer.camera.changed.removeEventListener(syncMap);
miniViewer.scene.preRender.removeEventListener(syncMap);
}
// 同步主图与鹰眼地图
function syncEyeMap() {
// 监听主图
new Cesium.ScreenSpaceEventHandler(viewer.canvas).setInputAction(() => {
isMainMapTrigger = true;
isEyeMapTrigger = false;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// 判断是否为主图移动
if (!isMainMapTrigger) {
return false;
}
/**
* 判断地图模式使用相应同步方式 1-哥伦比亚地图(2.5D)、2-二维地图(2D)、3-地球(3D)
* 哥伦比亚地图(2.5D);同步位置、旋转、倾斜
* 二维地图(2D);同步中心点位置
* 地球(3D):同步相机视角
* */
if (miniViewer.scene.mode == 2) {
// 获取地图中心点
let position = getCenterPosition()
if (!position) return
miniViewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(position.lon, position.lat, position.height),
duration: 0.0,
})
} else if (miniViewer.scene.mode == 1) {
// 解除lookAtTransform的锁定
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
miniViewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
// 设置位置视角
let viewTransform = getViewTransform(viewer)
var heading = viewer.camera.heading;
var pitch = viewer.camera.pitch;
miniViewer.camera.lookAtTransform(viewTransform.transform, new Cesium.HeadingPitchRange(heading, pitch, viewTransform.range));
} else {
miniViewer.camera.flyTo({
destination: viewer.camera.position,
orientation: {
heading: viewer.camera.heading,
pitch: viewer.camera.pitch,
roll: viewer.camera.roll,
},
duration: 0.0,
})
}
}
// 鹰眼地图与主图联动效果
function syncMap() {
// 监听鹰眼地图
new Cesium.ScreenSpaceEventHandler(miniViewer.canvas).setInputAction(() => {
isMainMapTrigger = false;
isEyeMapTrigger = true;
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
// 判断是否为鹰眼地图移动
if (!isEyeMapTrigger) {
return false;
}
if (viewer.scene.mode == 2) {
// 获取地图中心点
let position = getCenterPosition()
if (!position) return
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(position.lon, position.lat, position.height),
duration: 0.0,
})
} else if (viewer.scene.mode == 1) {
// 解除lookAtTransform的锁定
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
miniViewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
// 设置位置视角
let viewTransform = getViewTransform(miniViewer)
var heading = miniViewer.camera.heading;
var pitch = miniViewer.camera.pitch;
viewer.camera.lookAtTransform(viewTransform.transform, new Cesium.HeadingPitchRange(heading, pitch, viewTransform.range));
} else {
viewer.camera.flyTo({
destination: miniViewer.camera.position,
orientation: {
heading: miniViewer.camera.heading,
pitch: miniViewer.camera.pitch,
roll: miniViewer.camera.roll,
},
duration: 0.0,
})
}
}
/**
* 获取变换矩阵和到中心点的距离
* @param {*} viewObj 地图对象
* @return {transform, range} 变换矩阵,距离
*/
function getViewTransform(viewObj) {
let position = getCenterPosition()
if (!position) return
// 中心点
var centerPosition = Cesium.Cartesian3.fromDegrees(position.lon, position.lat, 0)
// 相机点
var endLat = Cesium.Math.toDegrees(viewObj.camera.positionCartographic.latitude)
var endlng = Cesium.Math.toDegrees(viewObj.camera.positionCartographic.longitude)
var height = viewObj.camera.positionCartographic.height;
var endPosition = Cesium.Cartesian3.fromDegrees(endlng, endLat, height)
// 距离
var range = Cesium.Cartesian3.distance(centerPosition, endPosition)
// 矩阵
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(position.lon, position.lat));
return {
transform: transform,
range: range
}
}
/**
* 获取地图中心点
* return {lon, lat, height} 经度,纬度,高度
*/
function getCenterPosition() {
let centerResult = null, height = 10000
// 是否鹰眼图触发
if (isEyeMapTrigger) {
centerResult = miniViewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
miniViewer.canvas.clientWidth / 2,
miniViewer.canvas.clientHeight / 2,
),
)
height = miniViewer.camera.positionCartographic.height;
} else {
centerResult = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
viewer.canvas.clientWidth / 2,
viewer.canvas.clientHeight / 2,
),
)
height = viewer.camera.positionCartographic.height;
}
if (!Cesium.defined(centerResult)) return false
let curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(centerResult);
let curLongitude = (curPosition.longitude * 180) / Math.PI;
let curLatitude = (curPosition.latitude * 180) / Math.PI;
return {
lon: curLongitude,
lat: curLatitude,
height: height
}
}
场景模式切换监听:这边逻辑是大地图切换完成在切小地图场景,完了在绑定事件监听;
/**场景完成监听事件 */
viewer.scene.morphComplete.addEventListener(() => {
// 小地图进行对应切换
if (mapMode == '2d') {
miniViewer.scene.morphTo2D(1)
} else if (mapMode == '3d') {
miniViewer.scene.morphTo3D()
} else {
miniViewer.scene.morphToColumbusView()
}
if (!centerPosition) return
// 延迟相机转场
let timeout = setTimeout(() => {
if (mapMode == '2d' || mapMode == '3d') {
let position = Cesium.Cartesian3.fromDegrees(centerPosition.lon, centerPosition.lat, centerPosition.height)
viewer.camera.flyTo({
destination: position,
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-35.0),
roll: 0.0,
},
});
} else {
var heading = viewer.camera.heading;
var pitch = viewer.camera.pitch;
viewer.camera.lookAtTransform(originalView.transform, new Cesium.HeadingPitchRange(heading, pitch, originalView.range));
}
clearTimeout(timeout)
}, 1000)
})
miniViewer.scene.morphComplete.addEventListener(() => {
if (!centerPosition) return
// 延迟相机转场
let timeout = setTimeout(() => {
if (mapMode == '2d' || mapMode == '3d') {
miniViewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(centerPosition.lon, centerPosition.lat, centerPosition.height),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-35.0),
roll: 0.0
},
})
} else {
var heading = viewer.camera.heading;
var pitch = viewer.camera.pitch;
miniViewer.camera.lookAtTransform(originalView.transform, new Cesium.HeadingPitchRange(heading, pitch, originalView.range));
}
bindEvent()
clearTimeout(timeout)
}, 1000)
})
切换场景:切换要先移除事件监听,获取切换前的参数(中心点、变换矩阵和距离)
/**
* 切换地图模式
* @param {*} mode 2d、3d、2.5d
*/
function changeMapMode(mode) {
// 解除绑定事件
removeEvent()
mapMode = mode
centerPosition = getCenterPosition()
if (mode == '2d') {
viewer.scene.morphTo2D(1)
} else if (mode == '3d') {
viewer.scene.morphTo3D()
} else {
// 记录转换前的变化矩阵和距离,变换后转场成相应视角
originalView = getViewTransform(viewer)
viewer.scene.morphToColumbusView()
}
}