一、使用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>