一、viewer.cesiumWidget.container.appendChild()
把你自定义的 HTML 元素(弹窗、按钮、图标等)添加到 Cesium 画布的容器里,让它显示在 3D 地球场景上。
// 1. 创建一个自定义弹窗 div
const infoDiv = document.createElement('div');
infoDiv.style.position = 'absolute';
infoDiv.style.top = '100px';
infoDiv.style.left = '100px';
infoDiv.style.background = 'white';
infoDiv.style.padding = '10px';
infoDiv.innerHTML = '我是显示在地球上的自定义弹窗!';
// 2. 关键:把 div 添加到 Cesium 根容器
viewer.cesiumWidget.container.appendChild(infoDiv);
二、viewer..entities.values作用
viewer.entities.values 是一个数组,里面包含了你在 Cesium 中添加的所有实体(点、线、面、标注、模型等),可以用来遍历、查询、修改、删除全部实体。
核心作用(最常用)
① 遍历所有实体(最常用)
批量修改、隐藏、删除所有实体:
// 遍历场景中所有实体
viewer.entities.values.forEach(entity => {
// 示例1:隐藏所有实体
entity.show = false;
// 示例2:修改所有点的颜色
if (entity.point) {
entity.point.color = Cesium.Color.RED;
}
});
② 获取实体总数
const count = viewer.entities.values.length;
console.log('场景中共有实体:', count);
③ 清空所有实体(替代 removeAll())
// 清空所有实体
viewer.entities.removeAll();
// 等价于遍历删除(不推荐,仅理解用)
viewer.entities.values.forEach(entity => {
viewer.entities.remove(entity);
});
④ 查找符合条件的实体
// 查找所有名称为 "测试点" 的实体
const targetEntities = viewer.entities.values.filter(e => e.name === '测试点');
三、viewer.scene.canvas.height
viewer.scene.canvas.height 用来获取 / 设置 Cesium 3D 地球画布的高度(像素值),直接控制地球显示区域的高度大小。
- viewer.scene.canvas
→ Cesium 真正渲染 3D 地球的画布元素(就是一个 <canvas> HTML 标签)
- .height
→ 这个 canvas 元素的高度属性(单位:像素 px)
核心作用
① 获取当前地球画布的真实高度(只读常用)
// 获取当前 Cesium 画布高度(像素)
const canvasHeight = viewer.scene.canvas.height;
console.log('地球高度:', canvasHeight);
② 动态修改地球高度(很少直接用)
// 强制把地球高度改成 500px
viewer.scene.canvas.height = 500;
正确获取显示高度:用 offsetHeight
如果你想知道页面上实际显示的地球高度,要用:
viewer.scene.canvas.offsetHeight // 真实显示高度(推荐)
因为:
canvas.height = 绘图分辨率高度(内部渲染尺寸)
canvas.offsetHeight = 页面显示高度(肉眼看到的尺寸)
两者不一定相等!
四、viewer.scene.postRender.addEventListener()
在 Cesium 地球每完成一帧渲染之后 **,自动执行你指定的代码,用来做实时更新、动画、跟随、动态效果等。
1. 它到底是什么?
viewer.scene.postRender
→ 渲染完成事件(每一帧渲染完都会触发一次)
addEventListener()
→ 给这个事件绑定一个监听函数
简单理解:
Cesium 地球每秒会刷新 60 次(60 帧)
每刷新完一帧画面,就立刻执行一次你写的函数
相当于一个无限循环的实时更新器
2. 核心作用(最常用场景)
它专门用来做必须实时更新的功能:
让弹窗 / 标签 跟随 3D 点位移动(最常用!)
动态修改实体属性(位置、颜色、大小)
自定义动画效果
实时计算相机位置
实时更新 UI 数据
3. 最典型使用示例(点位跟随弹窗)
// 1. 创建一个自定义 HTML 弹窗
const div = document.createElement('div');
div.style.position = 'absolute';
div.style.color = 'white';
div.innerHTML = '我会跟着点位动';
viewer.cesiumWidget.container.appendChild(div);
// 2. 重点:每帧渲染后都更新弹窗位置
viewer.scene.postRender.addEventListener(() => {
// 实时把 3D 坐标 → 屏幕坐标
const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(你的3D坐标);
if (canvasPosition) {
// 让弹窗跟着点位走
div.style.left = canvasPosition.x + 'px';
div.style.top = canvasPosition.y + 'px';
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>实体实时流畅移动</title>
<!-- 引入Cesium库 -->
<link
href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
/>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Arial", sans-serif;
background-color: #000;
color: #e0e0e0;
overflow: hidden;
height: 100vh;
}
#cesiumContainer {
width: 100%;
height: 100%;
position: absolute;
}
</style>
</head>
<body>
<!-- Cesium容器 -->
<div id="cesiumContainer"></div>
<script>
// 设置Cesium访问令牌(实际使用中需要替换为自己的token)
Cesium.Ion.defaultAccessToken =
"accessToken";
// 初始化地球视图
const viewer = new Cesium.Viewer("cesiumContainer", {
sceneMode: Cesium.SceneMode.SCENE3D,
animation: false,
timeline: false,
fullscreenButton: false,
homeButton: false,
geocoder: false,
baseLayerPicker: false,
navigationHelpButton: false,
infoBox: false,
selectionIndicator: false,
shadows: true,
terrainShadows: Cesium.ShadowMode.RECEIVE_ONLY,
orderIndependentTranslucency: false,
contextOptions: {
webgl: {
preserveDrawingBuffer: true,
},
},
});
// ========== 1. 创建一个固定的3D点位(实体) ==========
const position = Cesium.Cartesian3.fromDegrees(116.39748, 39.90882, 100); // 北京坐标
viewer.entities.add({
position: position,
point: {
color: Cesium.Color.RED,
pixelSize: 10,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
},
label: {
text: "固定点位",
font: "16px sans-serif",
fillColor: Cesium.Color.WHITE,
pixelOffset: new Cesium.Cartesian2(0, -20),
},
});
// ========== 2. 创建自定义 HTML 弹窗 ==========
const infoDiv = document.createElement("div");
infoDiv.style.position = "absolute";
infoDiv.style.background = "rgba(0,0,0,0.7)";
infoDiv.style.color = "white";
infoDiv.style.padding = "6px 10px";
infoDiv.style.borderRadius = "4px";
infoDiv.style.pointerEvents = "none"; // 不影响鼠标操作地球
infoDiv.style.fontSize = "14px";
infoDiv.innerHTML = "我会牢牢跟着3D点位 ✅";
// 添加到地球容器
viewer.cesiumWidget.container.appendChild(infoDiv);
// ========== 3. 每帧渲染 → 弹窗实时跟随 ==========
function updatePopup() {
// 把3D坐标 转为 屏幕2D坐标
const canvasPosition =
viewer.scene.cartesianToCanvasCoordinates(position);
if (canvasPosition) {
// 设置弹窗位置
infoDiv.style.left = canvasPosition.x + "px";
infoDiv.style.top = canvasPosition.y + "px";
}
}
// 绑定到每帧渲染后执行
viewer.scene.postRender.addEventListener(updatePopup);
</script>
</body>
</html>
效果:无论地球怎么旋转、缩放,弹窗永远牢牢贴在 3D 点位上。
4. 为什么要用它?
普通代码:只执行一次
postRender:每帧都执行(60 次 / 秒)
所以:
静态内容 → 不用
动态、跟随、实时变化 → 必须用 postRender
5. 重要注意事项
不要写太复杂的逻辑每秒执行 60 次,代码太卡会掉帧、卡顿。
不用时记得移除监听(避免内存泄漏)
// 移除监听
viewer.scene.postRender.removeEventListener(你的函数);
和 requestAnimationFrame 作用一样,但更适配 Cesium。