cesium项目中集成指北针(原生版)

 

一、使用Canvas绘制一个指北针

const canvas = document.getElementById('mycanvas');
const ctx = canvas.getContext('2d');
// 设置指北针中心点坐标和半径
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 50;
let currentAngle=0
// 绘制指北针外圈
function drawCompassCircle() {
    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
    ctx.strokeStyle = '#333';
    ctx.lineWidth = 3;
    ctx.stroke();
    ctx.closePath();
    ctx.beginPath()
    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI)
    ctx.fillStyle = 'transparent'
    ctx.fill()
    for (let i = 0; i < 360; i += 10) {
      const rad = Cesium.Math.toRadians(i)
      ctx.beginPath()
      ctx.moveTo(150 + Math.cos(rad) * 40, 75 + Math.sin(rad) * 40)
      ctx.lineTo(150 + Math.cos(rad) * 45, 75 + Math.sin(rad) * 45)
      ctx.strokeStyle = 'black'
      ctx.stroke()}
}

// 绘制指北针箭头
function drawArrow() {
    ctx.beginPath();
    // 箭头主体
    ctx.moveTo(0, -radius + 10); // 顶部
    ctx.lineTo(-10, 0); // 左翼
    ctx.lineTo(10, 0); // 右翼
    ctx.closePath();
    
    // 填充箭头颜色
    ctx.fillStyle = 'red';
    ctx.fill();

    // 绘制箭头边框
    ctx.strokeStyle = '#333';
    ctx.lineWidth = 2;
    ctx.stroke();
    
    // 绘制指北针尾部
    ctx.beginPath();
    ctx.moveTo(-5, 0); // 左翼
    ctx.lineTo(5, 0); // 右翼
    ctx.lineTo(0, radius - 20); // 尾部底端
    ctx.closePath();
    
    // 填充尾部颜色
    ctx.fillStyle = 'blue';
    ctx.fill();

    // 绘制尾部边框
    ctx.strokeStyle = '#333';
    ctx.lineWidth = 2;
    ctx.stroke();
}
// 更新指南针的航向
function updateHeading(heading) {
    ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
    drawCompassCircle(); // 重新绘制指北针外圈
    
    ctx.save(); // 保存当前的绘图状态
    ctx.translate(centerX, centerY); // 将绘图原点移到指北针中心
    ctx.rotate(heading * Math.PI / 180); // 根据航向角旋转
    drawArrow(); // 绘制箭头
    ctx.restore(); // 恢复到之前保存的绘图状态
}
export {
    updateHeading,
    currentAngle,
    canvas,
    centerX,
    centerY
}

 

二、HTML页面结构

<canvas id="mycanvas" class="compass"></canvas>
<div id="cesiumContainer"></div>

三、CSS样式

    .compass{
      position: fixed;
    top: 6%;
    right: 22%;
    height: 100px;
    width: 200px;
    z-index: 200;
    }

 

四、cesium的相机视角和指北针之间的相互交互


<script>
import * as Cesium from 'cesium'
import { updateHeading, canvas, centerX, centerY } from './CompassTwo'
export default {
    name: 'HelloWorld',
    props: {
        msg: String
    },
    data() {
        return {
            viewer: null,
            waterColor: "rgba(183, 149, 75, 0.91)",
            CesiumMap: null,
            isDragging: false,
            compassHeading: 0,
            currentAngle: 0,
            delta: 0,
            up: 0
        }
    },
    mounted() {
        //注册的token有问题
        this.initMap()
        //页面挂载完成时,先绘制一边指北针
        updateHeading(360)

        canvas.addEventListener('mousedown', (event) => {
            this.isDragging = true;
        })
        canvas.addEventListener('mousemove', (event) => {
            if (this.isDragging) {
                const mousePos = this.getMousePos(event);
                this.currentAngle = this.calculateAngle(mousePos.x, mousePos.y);
                var compassHeading = Cesium.Math.toDegrees(-this.currentAngle);
                updateHeading(-compassHeading);
            }
        })

        canvas.addEventListener('mouseup', () => {
            this.isDragging = false;
        })

        canvas.addEventListener('mouseleave', () => {
            this.isDragging = false;
        })
        //监听鼠标在指北针上滚动滚轮时指针转动的角度及方向
        canvas.addEventListener('wheel', (event) => {
            ;
            this.delta = event.deltaY;
            if (this.delta > 0) {
                this.up = this.up - 10
            } else {
                this.up = this.up + 10
            }
            updateHeading(this.up); // 更新箭头角度
        });
    },
    watch: {
        compassHeading(newval, oldval) {
            updateHeading(newval);

        },
        up(newval, oldval) {
            // 计算新的相机视角(这里只是示例,实际场景可能需要更复杂的逻辑)
            var camera = this.CesiumMap.camera;
            var newHeading = Cesium.Math.toRadians(newval); // 将角度转换为弧度
            // 获取当前相机位置和方向
            var position = camera.position;
            var direction = camera.direction;
            // 计算新的相机方向
            var newDirection = Cesium.Cartesian3.fromRadians(newHeading, Cesium.Math.toRadians(0), 0);
            // 设置新的相机视角
            camera.setView({
                destination: position,
                orientation: {
                    heading: Cesium.Math.toRadians(newval), // east, default value is 0.0 (north)
                    pitch: Cesium.Math.toRadians(-90),    // default value (looking down)
                    roll: 0.0                             // default value
            }
                });
    },
    currentAngle(newval, oldval) {
        if (Math.abs(newval - oldval) > 0.1) {
            // 计算新的相机视角(这里只是示例,实际场景可能需要更复杂的逻辑)
            var camera = this.CesiumMap.camera;
            var newHeading = this.currentAngle; // 将角度转换为弧度

            // 获取当前相机位置和方向
            var position = camera.position;
            var direction = camera.direction;

            // 计算新的相机方向
            var newDirection = Cesium.Cartesian3.fromRadians(newHeading, Cesium.Math.toRadians(0), 0);

            // 设置新的相机视角
            camera.setView({
                destination: position,
                orientation: {
                    direction: newDirection,
                    up: camera.up
                }
            });
        }
    }

},
methods: {
    initMap() {
        this.CesiumMap = new Cesium.Viewer("cesiumContainer", {
            geocoder: false,
            animation: false,
            timeline: false,
            infoBox: false,
            baseLayerPicker: false,
            fullscreenButton: false,
            homeButton: false,
            sceneModePicker: false,
            navigationHelpButton: false,
            CreditsDisplay: false,
            selectionIndicator: false,
        });
        //
        this.CesiumMap.scene.postRender.addEventListener(() => {
            const camera = this.CesiumMap.scene.camera;
            var heading = camera.heading;
            // 将heading转换为指南针需要的角度
            this.compassHeading = Cesium.Math.toDegrees(-heading);
            console.log(this.compassHeading);
        });
        this.CesiumMap._cesiumWidget._creditContainer.style.display = "none"; //LOGO显示
        const options = {
            // 默认视角
            defaultResetView: Cesium.Cartographic.fromDegrees(113.318977, 23.114155, 200),
            //相机方向
            orientation: { pitch: Cesium.Math.toRadians(-45) },
            //相机延时
            // duration = 4, //默认为3s
            // 用于启用或禁用罗盘。true是启用罗盘,false是禁用罗盘。默认值为true。如果将选项设置为false,则罗盘将不会添加到地图中。
            enableCompass: true,
            // 用于启用或禁用缩放控件。true是启用,false是禁用。默认值为true。如果将选项设置为false,则缩放控件将不会添加到地图中。
            enableZoomControls: true,
            // 用于启用或禁用距离图例。true是启用,false是禁用。默认值为true。如果将选项设置为false,距离图例将不会添加到地图中。
            enableDistanceLegend: true,
            // 用于启用或禁用指南针外环。true是启用,false是禁用。默认值为true。如果将选项设置为false,则该环将可见但无效。
            enableCompassOuterRing: true, //修改重置视图的tooltip
            resetTooltip: "重置视图",
            // 修改放大按钮的tooltip
            zoomInTooltip: "放大",
            // 修改缩小按钮的tooltip
            zoomOutTooltip: "缩小"
        }
        new CesiumNavigation(this.CesiumMap, options);
        this.CesiumMap.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(120.79579364922108, 31.41897182222492, 10500) })

        // this.createWater();
    },
    getMousePos(event) {
        const rect = canvas.getBoundingClientRect();
        return {
            x: event.clientX - rect.left,
            y: event.clientY - rect.top
        };
    },
    calculateAngle(mouseX, mouseY) {
        const dx = mouseX - centerX;
        const dy = mouseY - centerY;
        let angle = Math.atan2(dy, dx);
        let angleInRadians = angle < 0 ? (angle + 2 * Math.PI) : angle;
        return angleInRadians
    }


}
}
</script>

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值