news 2026/5/1 5:51:15

用Cesium做个地图标记功能?手把手教你实现点击获取经纬度的完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Cesium做个地图标记功能?手把手教你实现点击获取经纬度的完整流程

用Cesium实现地图标记功能:从点击事件到经纬度坐标的完整指南

第一次接触Cesium的三维地球开发时,最让我兴奋的就是能够像主流地图应用那样,通过点击获取任意位置的经纬度信息。这个看似简单的功能背后,其实隐藏着屏幕像素、三维空间和地理坐标三个不同维度的坐标系转换。本文将带你用不到100行代码,实现一个完整的坐标拾取工具。

1. 环境搭建与基础准备

在开始编写交互代码前,我们需要准备一个基础的Cesium开发环境。这里推荐使用CDN方式快速引入Cesium库,避免复杂的构建配置:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Cesium坐标拾取示例</title> <script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script> <link href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> <style> html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } </style> </head> <body> <div id="cesiumContainer"></div> <script> // 初始化Viewer const viewer = new Cesium.Viewer('cesiumContainer', { terrainProvider: Cesium.createWorldTerrain(), timeline: false, animation: false }); </script> </body> </html>

提示:使用createWorldTerrain()需要Cesium ion账号和token,如需离线开发可改用new Cesium.EllipsoidTerrainProvider()

基础场景中几个关键对象需要提前了解:

  • Viewer:整个三维场景的容器和控制器
  • Scene:包含所有图形对象的场景树
  • Camera:控制观察视角和投影方式
  • Globe:代表地球表面的地形和影像层

2. 坐标系系统深度解析

Cesium开发涉及三种核心坐标系,理解它们的区别和转换关系至关重要:

坐标系类型描述典型用途代表类
屏幕坐标二维像素坐标,原点在左上角鼠标点击位置Cartesian2
世界坐标三维直角坐标系,原点在地球中心空间位置计算Cartesian3
地理坐标经纬度高程表示的椭球面坐标地理信息存储Cartographic

转换流程遵循这样的链条:屏幕坐标 → 世界坐标 → 地理坐标

这个转换过程需要考虑地球曲率和地形高程。在平坦的地球模型下,转换相对简单,但真实场景中必须通过Globe.pick()方法考虑地形因素。

3. 实现点击拾取功能

现在我们来编写核心的点击事件处理代码。完整的实现包含三个关键步骤:

// 在Viewer初始化后添加以下代码 viewer.screenSpaceEventHandler.setInputAction((click) => { // 步骤1:获取屏幕坐标 const screenPosition = click.position; // 步骤2:屏幕坐标转世界坐标 const ray = viewer.camera.getPickRay(screenPosition); if (!ray) return; const worldPosition = viewer.scene.globe.pick(ray, viewer.scene); if (!worldPosition) return; // 步骤3:世界坐标转地理坐标 const cartographic = Cesium.Cartographic.fromCartesian(worldPosition); const longitude = Cesium.Math.toDegrees(cartographic.longitude); const latitude = Cesium.Math.toDegrees(cartographic.latitude); const height = cartographic.height; console.log(`经度: ${longitude.toFixed(6)}°, 纬度: ${latitude.toFixed(6)}°, 高程: ${height.toFixed(2)}米`); // 添加标记点 viewer.entities.add({ position: worldPosition, point: { pixelSize: 10, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 }, label: { text: `${longitude.toFixed(4)}°, ${latitude.toFixed(4)}°`, font: '14px sans-serif', style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.TOP, pixelOffset: new Cesium.Cartesian2(0, -15) } }); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

这段代码实现了完整的交互流程:

  1. 通过screenSpaceEventHandler监听左键点击事件
  2. 将点击位置的屏幕坐标转换为三维射线
  3. 通过globe.pick()获取射线与地表的交点
  4. 将世界坐标转换为人类可读的经纬度高程
  5. 在点击位置添加可视化标记

4. 高级功能扩展

基础功能实现后,我们可以进一步优化用户体验和功能完整性:

4.1 添加坐标显示面板

在HTML中添加一个显示面板:

<div id="coordinatePanel" style="position:absolute; top:10px; left:10px; background:white; padding:10px; border-radius:5px;"> 点击地图获取坐标 </div>

更新点击事件处理代码:

// 替换原来的console.log输出 const coordText = `经度: ${longitude.toFixed(6)}°<br>纬度: ${latitude.toFixed(6)}°<br>高程: ${height.toFixed(2)}米`; document.getElementById('coordinatePanel').innerHTML = coordText;

4.2 支持多点标记与清除

添加控制按钮:

<button id="clearPoints" style="position:absolute; top:60px; left:10px;">清除所有标记</button>

对应JavaScript代码:

document.getElementById('clearPoints').addEventListener('click', () => { viewer.entities.removeAll(); document.getElementById('coordinatePanel').innerHTML = '点击地图获取坐标'; });

4.3 地形精确度优化

在山区或复杂地形区域,可以开启更精确的地形采样:

viewer.terrainProvider = Cesium.createWorldTerrain({ requestWaterMask: true, requestVertexNormals: true }); // 在pick调用时指定详细级别 const worldPosition = viewer.scene.globe.pick(ray, viewer.scene, 9); // 9表示最高精度

5. 常见问题与调试技巧

在实际开发中,你可能会遇到以下典型问题:

问题1:点击海洋或空白区域返回null

  • 原因:射线没有与地表相交
  • 解决:添加有效性检查
if (!worldPosition) { console.warn('未点击到有效地形'); return; }

问题2:坐标精度不足

  • 原因:默认地形采样率有限
  • 解决:提高采样级别或使用本地高精度地形数据

问题3:标记点被地形遮挡

  • 解决:调整点实体的高度参考模式
viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height + 2), // 抬高2米 // ...其他属性 heightReference: Cesium.HeightReference.CLAMP_TO_GROUND });

调试时可以利用Cesium的内置工具:

// 开启调试模式 viewer.scene.debugShowFramesPerSecond = true; viewer.scene.globe.show = true; viewer.scene.globe.showGroundAtmosphere = true;

6. 性能优化建议

当需要处理大量标记点时,考虑以下优化策略:

  • 使用EntityCluster聚合显示密集点
viewer.dataSources.add(Cesium.EntityCluster.new());
  • 对于静态标记,改用Primitive API替代Entity API
viewer.scene.primitives.add(new Cesium.PointPrimitiveCollection({ modelMatrix: Cesium.Matrix4.IDENTITY, debugShowBoundingVolume: false }));
  • 按视距分级加载标记
viewer.scene.postRender.addEventListener(() => { const cameraHeight = viewer.camera.positionCartographic.height; // 根据相机高度调整标记显示细节 });

在最近的一个气象站项目中,我们使用类似的坐标拾取功能让用户可以标记异常天气位置。最初直接使用Entity API导致在移动端出现卡顿,后来改用Primitive结合视距检测,性能提升了3倍以上。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 5:50:59

Pyecharts实战指南:从入门到精通的数据可视化技巧

1. Pyecharts&#xff1a;数据可视化的瑞士军刀 第一次接触Pyecharts是在三年前的一个商业分析项目里&#xff0c;当时客户要求用动态图表展示销售数据。试过Matplotlib和Seaborn后&#xff0c;我发现它们生成的静态图表总是差那么点意思。直到发现了这个基于Echarts的Python库…

作者头像 李华
网站建设 2026/4/18 7:11:44

3步快速配置:Chrome独立代理的终极指南

3步快速配置&#xff1a;Chrome独立代理的终极指南 【免费下载链接】Chrome-proxy-helper Chrome PROXY extension, set proxy for Chrome browser 项目地址: https://gitcode.com/gh_mirrors/ch/Chrome-proxy-helper 你是否遇到过这样的烦恼&#xff1a;想要为Chrome浏…

作者头像 李华
网站建设 2026/4/16 11:09:12

ArcGIS Enterprise 10.8 单机部署避坑指南——Windows Server 2016 实战解析

1. 环境准备&#xff1a;避开那些"一失足成千古恨"的坑 第一次部署ArcGIS Enterprise的朋友们注意了&#xff0c;我见过太多人在环境准备阶段就埋下隐患。最典型的案例就是机器名和域名的设置问题——这玩意儿装好之后就像纹身一样改不了。千万别用arcgis.com或esri.…

作者头像 李华
网站建设 2026/4/16 11:09:12

Mac Mouse Fix:让普通鼠标在macOS上超越触控板的开源神器

Mac Mouse Fix&#xff1a;让普通鼠标在macOS上超越触控板的开源神器 【免费下载链接】mac-mouse-fix Mac Mouse Fix - Make Your $10 Mouse Better Than an Apple Trackpad! 项目地址: https://gitcode.com/GitHub_Trending/ma/mac-mouse-fix 你是否曾经为macOS上第三方…

作者头像 李华
网站建设 2026/4/16 11:07:19

开发环境瘦身指南:用WSL2命令将Ubuntu和Docker数据全量迁移到非系统盘

WSL2与Docker全量迁移实战&#xff1a;释放C盘空间的终极方案 每次打开资源管理器看到C盘飘红的剩余空间&#xff0c;作为开发者的你是否感到一阵窒息&#xff1f;那些被WSL2和Docker悄悄吞噬的磁盘空间&#xff0c;正在蚕食着我们宝贵的工作效率。本文将带你深入WSL2的存储机制…

作者头像 李华