cesium实现鹰眼图同步

同步视角


// 绑定事件
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()
    }
}

参考:Cesium基础代码段(五)鹰眼地图_cesium鹰眼图_Giser之路的博客-优快云博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值