前言
鼠标事件监听
Cesium中视图的变化监听使用的是viewer.screenSpaceEventHandler。
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
})
地理坐标系介绍(以WGS84为例)
World Geodetic System 1984,是为GPS全球定位系统使用而建立的坐标系统,坐标原点为地球质心,其地心空间直角坐标系的Z轴指向BIH (国际时间服务机构)1984.O定义的协议地球极(CTP)方向,X轴指向BIH 1984.0的零子午面和CTP赤道的交点,Y轴与Z轴、X轴垂直构成右手坐标系。我们平常手机上的指南针显示的经纬度就是这个坐标系下当前的坐标,进度范围[-180,180],纬度范围[-90,90]。
我们都知道Cesium目前支持两种坐标系WGS84和WebMercator,但是在Cesium中没有实际的对象来描述WGS84坐标,都是以弧度的方式来进行运用的也就是Cartographic类:new Cesium.Cartographic(longitude, latitude, height),这里的参数也叫longitude、latitude,就是经度和纬度,计算方法:弧度= π/180×经纬度角度。
笛卡尔空间直角坐标系(Cartesian3)
笛卡尔空间坐标的原点就是椭球的中心,我们在计算机上进行绘图时,不方便使用经纬度直接进行绘图,一般会将坐标系转换为笛卡尔坐标系,使用计算机图形学中的知识进行绘图。
平面坐标系(Cartesian2)
平面坐标系也就是平面直角坐标系,是一个二维笛卡尔坐标系,与Cartesian3相比少了一个z的分量,new Cesium.Cartesian2(x, y)。Cartesian2经常用来描述屏幕坐标系,比如鼠标在电脑屏幕上的点击位置,返回的就是Cartesian2,返回了鼠标点击位置的xy像素点分量。
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link href="../../Cesium/Widgets/widgets.css" rel="stylesheet">
<script type="text/javascript" src="../../Cesium/Cesium.js"></script>
<title>点击地球获取位置</title>
</head>
<body style="margin: 0px;width:100%;height:100%;">
<div id="cesiumContainer" style="width:100%;height:100%;position:absolute;"></div>
<div id="info" style="position: absolute;top:0px;left:0px;max-width: 500px;background-color: #fff;">
</div>
</body>
<script>
//created by onegiser at 2021-09-30
const key="天地图key"
const viewer = new Cesium.Viewer('cesiumContainer', {
imageryProviderViewModels: [
new Cesium.ProviderViewModel({
name: "天地图影像",
iconUrl: "/imgs/map/tdt_img.jpg",
tooltip: "",
creationFunction: () => {
const imgImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
url: "http://t{s}.tianditu.com/img_c/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" + key,
subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
tilingScheme: new Cesium.GeographicTilingScheme(),
tileMatrixLabels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"]
})
return [imgImageryProvider]
}
}),
]
})
let e
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
const { position } = movement//屏幕坐标
//屏幕坐标转化为笛卡尔坐标
const ray = viewer.camera.getPickRay(position);
const cartesian3 = viewer.scene.globe.pick(ray, viewer.scene);
//笛卡尔坐标转经纬度
const radians = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
const lat = Cesium.Math.toDegrees(radians.latitude); //弧度转度
const lng = Cesium.Math.toDegrees(radians.longitude);
const alt = radians.height;
//笛卡尔坐标转屏幕坐标
const _position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian3);
//经纬度转笛卡尔坐标
const _cartesian3 = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
//弧度转笛卡尔坐标
const _cartesian3_2 = Cesium.Cartesian3.fromRadians(radians.longitude, radians.latitude, radians.height)
//度转弧度
const _radians = {
longitude: Cesium.Math.toRadians(lng),
latitude: Cesium.Math.toRadians(lat),
height: alt
}
const str = `
屏幕坐标:(${position.x},${position.y})<br/>
笛卡尔坐标:(${cartesian3.x},${cartesian3.y},${cartesian3.z})<br/>
弧度:(${radians.longitude},${radians.latitude},${radians.height})<br/>
经纬度:(${lng},${lat},${alt})
通过反转化得到的屏幕坐标:(${_position.x},${_position.y})<br/>
通过反转化得到的笛卡尔坐标:(${_cartesian3.x},${_cartesian3.y},${_cartesian3.z})<br/>
通过反转化得到的笛卡尔坐标2:(${_cartesian3_2.x},${_cartesian3_2.y},${_cartesian3_2.z})<br/>
通过反转化得到的弧度:(${_radians.longitude},${_radians.latitude},${_radians.height})<br/>
`
console.log(str);
document.getElementById("info").innerHTML = `<div>${str}</div>`
if (e) {
viewer.entities.remove(e);
}
const entityOption = {
name: "通过鼠标点击地图添加实体",
position: cartesian3,
point: new Cesium.PointGraphics({
color: Cesium.Color.RED,
outlineColor: Cesium.Color.RED,
pixelSize: 10,
outlineWidth: 1,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}),
label: {
font: "30px sans-serif",
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
text: `${lng},${lat},${alt}`,
outlineColor: Cesium.Color.RED,
outlineWidth: 1,
fillColor: Cesium.Color.RED,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
pixelOffset: new Cesium.Cartesian2(0, 20)
}
}
e = viewer.entities.add(entityOption);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
</script>
</html>