cesium相机的按钮操作api封装

javascript 复制代码
class CameraNavigation {
    constructor(viewer) {
        this.viewer = viewer;
        this.flyDuration = 0.5
        this.clickEvent = true;
        this.moveEndHandler = null;
        this.speed = null
        this.moveSpeed = null;
        this.height = null;
        this.buttonEvent = {};
        this.rotationSpeed = 10;
        this.customZoomStep = 200;
        this.deviceType = this.getDeviceType();
        this.initControl()

        this.btnSAddEventListenerName = []
    }
    getDeviceType() {
        const userAgent = navigator.userAgent;
        console.log(userAgent);
        if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
            return "平板";
        } else if (
            /(mobi|opera mini|iphone|ipod|android|blackberry|windows phone)/i.test(
                userAgent
            )
        ) {
            return "手机";
        } else {
            return "电脑";
        }
    }
    initControl() {
        this.downStart = 'touchstart';
        this.upEnd = 'touchend';
        if (this.deviceType == "电脑") {
            this.downStart = "mousedown"
            this.upEnd = "mouseup"
        }
        console.log(this.upEnd, this.downStart);
    }
    setCameraPitch(pitch = 5){
        const camera = this.viewer.camera;

        // 获取当前相机的方向(heading 和 pitch)
        const currentHeading = camera.heading;
        const currentPitch = camera.pitch;
        console.log(currentPitch, 'currentPitch');
        // 将相机的方向设置为新的 roll,保持 heading 和 pitch 不变
        camera.setView({
            orientation: {
                heading: currentHeading,
                pitch: currentPitch + Cesium.Math.toRadians(pitch),
                roll: camera.roll,
            },
        });
    }
    zoomMap(direction) {
        const camera = this.viewer.camera;
        const position = camera.positionWC.clone();
        const directionVector = camera.directionWC.clone();
        const height = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height;

        // 根据相机高度调整缩放的比例
        // const scale = Math.ceil(height / 1000.0);
        // console.log(scale,'scale');
        // let dire = scale>1?scale*direction * 100:direction * 100
        // console.log(dire,'dire');
        const scale = Math.ceil(height / 1.0);
        let dire = scale * direction

        // 方向矢量与缩放量的乘积
        const zoomVector = Cesium.Cartesian3.multiplyByScalar(directionVector, dire, new Cesium.Cartesian3());

        // 新位置为当前位置加上缩放后的矢量
        const newPosition = Cesium.Cartesian3.add(position, zoomVector, new Cesium.Cartesian3());
        const heading = camera.heading;
        const pitch = camera.pitch;
        camera.flyTo({
            destination: newPosition,
            orientation: {
                heading: heading,
                pitch: pitch,
            },
            duration: 0.5, // 调整飞行动画的持续时间
        });
    }
    // 缩小地图
    zoomOut() {
        try {
            var currentDistance = this.viewer.camera.positionCartographic.height;
            var currentLongitude = this.viewer.camera.positionCartographic.longitude;
            var currentLatitude = this.viewer.camera.positionCartographic.latitude;

            var newDistance = currentDistance + this.customZoomStep;
            var newLongitude = currentLongitude;
            var newLatitude = currentLatitude;
            this.viewer.camera.flyTo({
                destination: Cesium.Cartesian3.fromRadians(newLongitude, newLatitude, newDistance),
                orientation: {
                    heading: this.viewer.camera.heading, // 保持航向角不变
                    pitch: this.viewer.camera.pitch,
                    roll: this.viewer.camera.roll
                },
                duration:0.5
            })

        } catch (error) {
            console.log(error, 'error');
        }
    }
    setCameraHeight(insertStep) {
        try {
            var currentDistance = this.viewer.camera.positionCartographic.height;
            var currentLongitude = this.viewer.camera.positionCartographic.longitude;
            var currentLatitude = this.viewer.camera.positionCartographic.latitude;

            var newDistance = currentDistance + insertStep;
            var newLongitude = currentLongitude;
            var newLatitude = currentLatitude;
            this.viewer.camera.flyTo({
                destination: Cesium.Cartesian3.fromRadians(newLongitude, newLatitude, newDistance),
                orientation: {
                    heading: this.viewer.camera.heading, // 保持航向角不变
                    pitch: this.viewer.camera.pitch,
                    roll: this.viewer.camera.roll
                },
                duration:0.5
            })
        } catch (error) {
            console.log(error, 'error');
        }
    }
    // 放大地图
    zoomIn() {
        try {
            var currentDistance = this.viewer.camera.positionCartographic.height;
            var currentLongitude = this.viewer.camera.positionCartographic.longitude;
            var currentLatitude = this.viewer.camera.positionCartographic.latitude;

            var newDistance = currentDistance - this.customZoomStep;
            var newLongitude = currentLongitude;
            var newLatitude = currentLatitude;
            if (currentDistance > 0) {
                this.viewer.camera.flyTo({
                    destination: Cesium.Cartesian3.fromRadians(newLongitude, newLatitude, newDistance),
                    orientation: {
                        heading: this.viewer.camera.heading, // 保持航向角不变
                        pitch: this.viewer.camera.pitch,
                        roll: this.viewer.camera.roll
                    },
                    duration:0.5
                })
            }
        } catch (error) {
            console.log(error, 'error');
        }
    }
    setupEventListeners() {
        if (this.moveSpeed) {
            this.speed = this.moveSpeed
        }
        let currentHeightInit = this.viewer.camera.positionCartographic.height;
        this.height = Math.round(currentHeightInit);

        // 添加高度变化监听事件
        this.moveEndHandler = () => {
            console.log(111);
            const currentHeight = this.viewer.camera.positionCartographic.height;
            this.height = Math.round(currentHeight);
            if (!this.moveSpeed) {
                this.speed = this.height / 100
            } else {
                this.speed = this.moveSpeed
            }
        }
        this.viewer.camera.moveEnd.addEventListener(this.moveEndHandler);
        console.log(this.height, 'this.height');

    }
    setupCameraNavigation() {
        // 定义事件处理函数
        function handleKeyDown(event) {
            console.log(event.key);
            switch (event.key) {
                // case 'ArrowUp' || 'w':
                case 'w':
                    this.moveCamera("Up");
                    break;
                // case 'ArrowDown' || 'd':
                case 's':
                    this.moveCamera("Down");
                    break;
                // case 'ArrowLeft' || 's':
                case 'a':
                    this.moveCamera("Left");
                    break;
                // case 'ArrowRight' || 'a':
                case 'd':
                    this.moveCamera("Right");
                    break;
                case 'q':
                    this.rotationCamera(10);
                    break;
                case 'e':
                    this.rotationCamera(-10);
                    break;
                default:
                    break;
            }
        }

        // 添加键盘按下事件监听器
        document.addEventListener('keydown', handleKeyDown.bind(this));
    }

    removeCameraNavigation() {
        try {
            this.btnSAddEventListenerName.forEach(ele => {
                if (this.clickEvent) {
                    document.querySelector(ele.id).removeEventListener('click', this.buttonEvent[ele.eventName].up, false)
                } else {
                    document.querySelector(ele.id).removeEventListener(this.downStart, this.buttonEvent[ele.eventName].up, false)
                    document.querySelector(ele.id).removeEventListener(this.upEnd, this.buttonEvent[ele.eventName].upEnd, false)
                }
            })
            // 移除键盘按下事件监听器
            // document.removeEventListener('keydown', this.handleKeyDown);
            // 取消高度变化监听事件
            this.viewer.camera.moveEnd.removeEventListener(this.moveEndHandler);
            this.btnSAddEventListenerName = []
            this.buttonEvent = {}
        } catch (error) {
            console.log(error, 'error');
        }
    }

    moveCamera(type = 'Up') {
        try {
            // 获取当前Cesium相机
            const camera = this.viewer.camera;

            // 获取当前相机的位置和方向
            const currentPosition = camera.positionCartographic.clone();
            const currentHeading = camera.heading;

            // 定义移动的距离和方向
            const distance = this.speed; // 1000米示例距离
            let bearing = Cesium.Math.toDegrees(currentHeading); // 使用当前方向

            switch (type) {
                case 'Up': // 向上移动
                    bearing = Cesium.Math.toDegrees(currentHeading)
                    break;
                case 'Down': // 向下移动
                    bearing = Cesium.Math.toDegrees(currentHeading - Math.PI); // 使用当前方向
                    break;
                case 'Left': // 向左移动
                    bearing = Cesium.Math.toDegrees(currentHeading - Math.PI / 2); // 使用当前方向
                    break;
                case 'Right': // 向右移动
                    bearing = Cesium.Math.toDegrees(currentHeading + Math.PI / 2); // 使用当前方向
                    break;
                default:
                    break;
            }
            // 使用Turf.js计算新位置
            const destination = turf.destination(
                turf.point([Cesium.Math.toDegrees(currentPosition.longitude), Cesium.Math.toDegrees(currentPosition.latitude)]),
                distance,
                bearing,
                { units: 'meters' }
            );
            // 将新位置转换为Cesium坐标
            const newCartesian = Cesium.Cartesian3.fromDegrees(destination.geometry.coordinates[0], destination.geometry.coordinates[1], this.height);

            // 设置相机位置
            // camera.position = newCartesian;

            camera.flyTo({
                destination: newCartesian,
                orientation: {
                    heading: camera.heading,
                    pitch: camera.pitch,
                    roll: camera.roll
                },
                duration: this.flyDuration
            })
        } catch (error) {
            console.log(error, 'error');
        }
    }
    // rotationCamera(n) {

    //     // 获取当前相机
    //     const camera = this.viewer.camera;

    //     // 获取当前相机的方向(heading)
    //     const currentHeading = camera.heading;

    //     // 设置旋转后的方向(顺时针旋转10度)
    //     const newHeading = currentHeading + Cesium.Math.toRadians(n);

    //     // 将相机旋转到新的方向
    //     camera.setView({
    //         orientation: {
    //             heading: newHeading,
    //             pitch: camera.pitch,
    //             roll: camera.roll,
    //         },
    //     });
    // }
    rotationCamera(n) {
        let centerScreen = this.getScreenCenterCoordinates();
        console.log(centerScreen, 'getScreenCenterCoordinates');
        // 获取当前相机
        const camera = this.viewer.camera;
        // console.log(camera.position, 'camera');

        let p = this.Cartesian3_to_WGS84(camera.position)
        // console.log(p, 'ppp');
        // 获取当前相机的方向(heading)
        var point1 = turf.point(centerScreen);
        var point2 = turf.point(p);
        var options = { units: 'meters' };
        var bearing = turf.bearing(point1, point2);
        var bearing1 = turf.bearing(point2, point1);
        console.log(bearing, bearing1, 'bearing1bearing1');
        var distance = turf.distance(point1, point2, options);
        // console.log(Cesium.Math.toRadians(n), 'Cesium.Math.toRadians(n)Cesium.Math.toRadians(n)');
        let newBearing = bearing + n;
        console.log(newBearing, 'newBearing');

        var destination = turf.destination(point1, distance, newBearing, options);
        let newP = destination.geometry.coordinates
        newP.push(p[2])
        // console.log(newP, 'destination');
        const currentHeading = camera.heading;
        // const currentHeading = camera.heading;
        // const newHeading = currentHeading + Cesium.Math.toRadians(n);
        // if (Math.abs(newBearing) < 9) {
        //     camera.setView({
        //         orientation: {
        //             heading: newHeading,
        //             pitch: camera.pitch,
        //             roll: camera.roll,
        //         },
        //     });
        //     return null
        // }
        // console.log(currentHeading,'currentHeading');
        let bearingCamera = 0;
        if (newBearing >= 0) {
            bearingCamera = newBearing - 180
        } else {
            bearingCamera = newBearing + 180
        }
        // 将相机旋转到新的方向
        camera.setView({
            destination: Cesium.Cartesian3.fromDegrees(newP[0], newP[1], newP[2]),
            orientation: {
                heading: Cesium.Math.toRadians(bearingCamera),
                pitch: camera.pitch,
                roll: camera.roll,
            },
        });
    }
    Cartesian3_to_WGS84(point) {
        var cartesian3 = new Cesium.Cartesian3(point.x, point.y, point.z);
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
        var lat = Cesium.Math.toDegrees(cartographic.latitude);
        var lng = Cesium.Math.toDegrees(cartographic.longitude);
        var alt = cartographic.height.toFixed(2);
        return [
            lng,
            lat,
            alt,
        ];
        // return {
        //     lng: lng,
        //     lat: lat,
        //     alt: alt,
        // };
    }
    //屏幕中点经纬度坐标
    getScreenCenterCoordinates() {
        // 范围对象
        let coordinates = undefined;

        // 得到当前三维场景
        let scene = this.viewer.scene;

        // 得到当前三维场景的椭球体
        let ellipsoid = scene.globe.ellipsoid;

        // 通过scene获取canvas长宽
        // let canvas = scene.canvas;
        // const canvasWidth = canvas.width;
        // const canvasHeight = canvas.height;

        改为获取body长宽 ,通过scene获取canvas在其他分辨率下存在兼容性问题
        const canvasWidth = document.body.clientWidth;
        const canvasHeight = document.body.clientHeight;

        // canvas中点
        let car3_center = this.viewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvasWidth / 2, canvasHeight / 2), ellipsoid);
        let xcarto_center = undefined;
        let ycarto_center = undefined;
        // 当canvas中点在椭球体上
        if (car3_center) {
            let carto_center = ellipsoid.cartesianToCartographic(car3_center);
            xcarto_center = Cesium.Math.toDegrees(carto_center.longitude);
            ycarto_center = Cesium.Math.toDegrees(carto_center.latitude);
        }

        // 获取高度
        let height = (this.viewer.camera.positionCartographic.height).toFixed(2);
        coordinates = [xcarto_center, ycarto_center, height];
        return coordinates;
    }
    addButtonTransformEvent(id, eventName) {
        try {
            let timer = null
            let button = document.querySelector(id);
            let eventNameString = eventName;
            let findObj = this.btnSAddEventListenerName.find(ele => ele.id == id)
            if (findObj) {
                return
            } {
                this.btnSAddEventListenerName.push({
                    id: id,
                    eventName: eventName
                })
            }
            if (button) {
                if (this.clickEvent) {
                    this.buttonEvent[eventName] = {}
                    this.buttonEvent[eventName].up = () => {
                        if (eventNameString == "moveForward") {
                            this.moveCamera("Up");
                        } else if (eventNameString == "moveBackward") {
                            this.moveCamera("Down");
                        }
                        else if (eventNameString == "moveLeft") {
                            this.moveCamera("Left");
                        }
                        else if (eventNameString == "moveRight") {
                            this.moveCamera("Right");
                        }
                        else if (eventNameString == "rotation+") {
                            this.rotationCamera(this.rotationSpeed);
                        }
                        else if (eventNameString == "rotation-") {
                            this.rotationCamera(-this.rotationSpeed);
                        }

                    }
                    button.addEventListener("click", this.buttonEvent[eventName].up, false)
                }
                else {
                    this.buttonEvent[eventName] = {}
                    this.buttonEvent[eventName].up = () => {
                        if (timer) {
                            clearInterval(timer)
                        }

                        timer = setInterval(() => {
                            console.log('按钮被按下!');
                            if (eventNameString == "moveForward") {
                                this.moveCamera("Up");
                            } else if (eventNameString == "moveBackward") {
                                this.moveCamera("Down");
                            }
                            else if (eventNameString == "moveLeft") {
                                this.moveCamera("Left");
                            }
                            else if (eventNameString == "moveRight") {
                                this.moveCamera("Right");
                            }
                            else if (eventNameString == "rotation+") {
                                this.rotationCamera(this.rotationSpeed);
                            }
                            else if (eventNameString == "rotation-") {
                                this.rotationCamera(-this.rotationSpeed);
                            }
                        }, 30);
                        console.log(eventNameString, 'eventName');
                    }
                    button.addEventListener(this.downStart, this.buttonEvent[eventName].up, false)
                    this.buttonEvent[eventName].upEnd = () => {
                        clearInterval(timer)
                        console.log('按钮被松开!');
                    }
                    button.addEventListener(this.upEnd, this.buttonEvent[eventName].upEnd, false);
                }
            }
        } catch (error) {
            console.log(error, 'error');
        }

    }
}
相关推荐
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
吖秧吖1 小时前
three.js 杂记
开发语言·前端·javascript
前端小超超1 小时前
vue3 ts项目结合vant4 复选框+气泡弹框实现一个类似Select样式的下拉选择功能
前端·javascript·vue.js
大叔是90后大叔1 小时前
vue3中查找字典列表中某个元素的值
前端·javascript·vue.js
IT大玩客2 小时前
JS如何获取MQTT的主题
开发语言·javascript·ecmascript