Three.js教程
cesium
实现地图上添加标签

cesium 实现地图上添加标签

今天,我们来一起看一下如何在 cesium 增加标签,下面我在地图上增加北京的字样,并且能够快速定位北京的地点,先看下效果。

搭建 cesium 的项目,大家可以看之前的使用 vite 搭建项目的文章,这里就不过多叙述了。 https://mp.weixin.qq.com/s/2odNqZZdKYJViAC-f4Vzdg?token=1735587643&lang=zh_CN (opens in a new tab)

实现步骤

  • 确定目标坐标
    • 通过 Cartesian3.fromDegrees(116.3912757, 39.906217, 0) 将北京的经纬度转换为 Cesium 中使用的三维笛卡尔坐标。该位置将用于后续实体的锚点(即图标和标签所处的位置)。
  • 创建实体并设置图标(Billboard)
    • 调用 viewer.entities.add(...) 创建一个新的 Entity 对象,并指定以下属性:
      • position: 实体的位置,使用上一步获取的坐标。
      • billboard: 通过 image(图标路径)、verticalOrigin(垂直对齐)、scale(图标大小)、color(整体颜色)等来定义图标的外观和摆放方式。
  • 添加文字标签(Label)
    • 在同一个实体中设置 label 属性,用于在图标旁边显示文字说明:
      • text 指定标签文字内容(如“北京”)。
      • fontstyleoutlineWidth 等属性则设定文字的字体、样式和描边。
      • verticalOriginpixelOffset 则决定标签与图标之间的对齐和相对偏移,让文字显示在合适的位置。
  • 飞行定位到指定位置
    • 使用 viewer.camera.flyTo(...) 将摄像机视角平滑移动至刚才标注的位置上空,并通过第三个参数设置高度(这里约 50,000 米)。这样用户即可在进入场景后迅速聚焦到标注点上,形成直观的三维地球定位效果。

确定目标坐标

// 添加一个图标点(以北京为例)
const position = Cartesian3.fromDegrees(116.3912757, 39.906217, 0);

通过该行代码,我们就取得了一个可以用于定位(position)的三维坐标。

  • Cesium 中的世界坐标并非直接使用经纬度,而是使用笛卡尔坐标 (Cartesian)。
  • fromDegrees(lng, lat, height) 方法可以将我们熟悉的地理坐标(经纬度 + 高度)转化为 Cesium 可识别的世界坐标系(WGS84)。
  • 这里示例使用了北京的经纬度:经度 116.3912757,纬度 39.906217。第三个参数 0 表示高度(海拔),即贴近地面。

添加实体(Entity)并设置图标

const icon = viewer.entities.add({
  position: position,
  billboard: {
    image: "/pin.png", // 图标图片路径
    verticalOrigin: 0, // 垂直对齐方式
    scale: 0.5, // 图标大小
    color: Color.RED, // 图标颜色
  },
  label: {
    text: "北京", // 图标标签文字
    font: "14pt monospace",
    style: 0,
    outlineWidth: 2,
    verticalOrigin: 1,
    pixelOffset: new Cartesian2(0, -9),
  },
});

1. viewer.entities.addEntity

  • 在 CesiumJS 中,Entity 是对三维场景中可视化对象的抽象,几乎所有在地图上呈现的对象都可以通过 Entity 来实现。
  • 使用 viewer.entities.add(...) 可以轻松地将一个实体对象加入到当前 Cesium 场景。

2. position

  • position 属性指定了实体在三维空间中的位置,这里直接引用了前面创建的 position 变量(北京坐标)。

3. billboard(广告牌/图标)

  • image:
    • 指定图标的资源路径或 URL,这里引用本地 /pin.png 文件。
    • 可以使用相对路径(如 ./pin.png)或绝对路径(如 https://yourdomain.com/pin.png),需要根据项目资源存放位置进行调整。
  • verticalOrigin:
    • 控制图标在垂直方向上的对齐方式。
    • 0 通常表示 底部对齐Cesium.VerticalOrigin.BOTTOM),也就是图标底边与定位点重合。
  • scale:
    • 表示图标缩放比例,0.5 意味着显示的图标大小是原图的 50%。
    • 如果想让图标更大或更小,可以修改这个数值。
  • color:
    • 使用 Color.RED 将图标整体调成红色。
    • Cesium 中的 Color 可以灵活设置透明度、渐变等。如果只想改变透明度,可使用 Color.RED.withAlpha(0.5) 等。

4. label(标签)

  • text:
    • 这里设置了 "北京",用以标注图标所代表的城市名称。
  • font:
    • 字体样式,如 "14pt monospace",可以根据需求更改为 "16px sans-serif" 等浏览器支持的字体格式。
  • style:
    • 文字样式的枚举值,0 对应 Cesium 中的 LabelStyle.FILL,表示纯色填充。
    • 若想显示描边文字,可使用 Cesium.LabelStyle.OUTLINE 或结合 outlineWidth 使用。
  • outlineWidth:
    • 文字描边的宽度,设置为 2 可以让文字边缘更清晰。
  • verticalOrigin:
    • billboard 类似,控制文字的垂直对齐方式。
    • 1 通常表示 基线对齐Cesium.VerticalOrigin.BASELINE)。
  • pixelOffset:
    • 以像素为单位设置文字相对实体位置的偏移量。
    • 这里设置为 new Cartesian2(0, -9),表示在 y 轴上向上移动 9 像素,让文字位于图标上方或附近。

通过这部分配置,我们可以同时展示图标(Billboard)与文字标签(Label),在三维地图上形成对地点的直观标注。

## 摄像机视角定位

viewer.camera.flyTo({
  destination: Cartesian3.fromDegrees(116.3912757, 39.906217, 50000),
});
  1. camera 属性
    • viewer.camera 是 Cesium 中对摄像机(视角)的全局管理对象,我们可以通过它来控制视角的位置、角度及运动方式。
  2. flyTo 方法
    • flyTo 会使摄像机平滑地移动到指定的位置,带有动画效果,让用户在浏览器中感受到“飞”向目标地的过程。
  3. destination
    • position 类似,这里依然使用 Cartesian3.fromDegrees 获取目标笛卡尔坐标。
    • 不同之处是第三个参数给出了一个较大的数值 50000(单位为米),代表我们想要在北京上空约 50 公里处查看场景。
    • 值越大,代表视野越远,能看到的范围也会越广。

当这行代码执行时,场景会把用户的视角逐步移动到北京这个坐标点上方 50 公里的位置,同时保留一定倾斜度,让地图看起来更有空间感。

代码

import { Ion, Viewer, Cartesian3, Color, Cartesian2 } from "cesium";
import "cesium/Build/Cesium/Widgets/widgets.css";
 
// Your access token can be found at: https://ion.cesium.com/tokens.
// Replace `your_access_token` with your Cesium ion access token.
 
Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6Ixxx";
 
// Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
const viewer = new Viewer("cesiumContainer");
 
// 添加一个图标点(以北京为例)
const position = Cartesian3.fromDegrees(116.3912757, 39.906217, 0);
 
// 添加一个实体(Entity)作为图标
const icon = viewer.entities.add({
  position: position,
  billboard: {
    image: "/pin.png", // 图标图片路径
    verticalOrigin: 0, // 垂直对齐方式
    scale: 0.5, // 图标大小
    color: Color.RED, // 图标颜色
  },
  label: {
    text: "北京", // 图标标签文字
    font: "14pt monospace",
    style: 0,
    outlineWidth: 2,
    verticalOrigin: 1,
    pixelOffset: new Cartesian2(0, -9),
  },
});
 
// 将视角定位到图标位置
viewer.camera.flyTo({
  destination: Cartesian3.fromDegrees(116.3912757, 39.906217, 50000),
});