Cesium中如何监听地图点击事件并获取经纬度?

萌新.钰浩 阅读 25

我在用Cesium做地图应用,想实现点击地图时弹出当前点的经纬度,但不知道怎么绑定点击事件。试过用viewer.screenSpaceEventHandler,但拿到的坐标是笛卡尔坐标,转成经纬度后数值很奇怪,是不是哪里弄错了?

下面是我现在的代码:

viewer.screenSpaceEventHandler.setInputAction(function(movement) {
  const cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
  if (cartesian) {
    const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    const lon = Cesium.Math.toDegrees(cartographic.longitude);
    const lat = Cesium.Math.toDegrees(cartographic.latitude);
    console.log('Lon:', lon, 'Lat:', lat);
  }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
欧阳悦弘
你这代码问题出在 pickEllipsoid 上,它只在当前相机能“看到”的地表球体上拾取点,如果地图有地形起伏或者你开了 3D Tiles,那它就直接穿过去拾取不到点,或者拾取到错误的位置。

前端这块更稳妥的做法是用 viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe),但其实更推荐用 viewer.scene.pickPosition(movement.position),它会考虑地形高度(DEM),返回真实地表的笛卡尔坐标,再转经纬度就准了。

另外你得注意:如果场景是 2D 或 Columbus View,得用 viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);如果是 3D,最好用 pickPosition

给你改个通用点的写法,兼容 2D 和 3D:

viewer.screenSpaceEventHandler.setInputAction(function(movement) {
// 尝试拾取地形上的真实位置(支持 3D Tiles 和地形)
let cartesian = viewer.scene.pickPosition(movement.position);

// 如果 pickPosition 失败(比如没点到地表),再 fallback 到球体拾取
if (!cartesian) {
cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
}

if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height; // 这个 height 是地形高程,不是相机高度
console.log('Lon:', lon.toFixed(6), 'Lat:', lat.toFixed(6), 'Height:', height.toFixed(2));
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);


注意 Cartographic.fromCartesian 是 Cesium 内部标准方法,你原代码没问题,主要是拾取逻辑太脆弱。
如果还是不准,大概率是你地图没开地形服务,或者场景里有遮挡物(比如 3D 建筑挡住了点击点),这时候 pickPosition 就会返回 undefined
可以加个 console.log(cartesian) 看下到底拾取到没,别光看经纬度奇怪就以为是转换错了。
点赞 4
2026-02-24 10:00