viewer.scene.requestRender
- 发布时间: 2026-02-12 09:19:01
- 相关标签: cesium requestRender
- 简介: 你想要深入了解 viewer.scene.requestRender() 这个方法,我会从它的作用、原理、使用场景和最佳实践等方面为你做全面讲解,帮你彻底掌握这个关键方法。
手机扫码查看
一、核心概念:requestRender() 是什么?
在 Cesium 中,viewer.scene.requestRender() 是触发场景重新渲染的核心方法。
1. 基础定义
Cesium 的场景渲染默认是按需渲染(不是每一帧都无脑渲染):
- 当相机移动、实体位置变化、时间推进等「主动操作」发生时,Cesium 会自动触发渲染;
- 当你做了「Cesium 无法自动感知」的修改(比如手动修改几何体顶点、自定义材质参数、非 Cesium 原生事件驱动的属性变化),就需要手动调用
requestRender()告诉 Cesium:“场景变了,该重新画一帧了”。
2. 底层原理
- Cesium 内部维护一个「渲染请求标记」,
requestRender()会将这个标记置为true; - Cesium 的渲染循环(
requestAnimationFrame驱动)每帧都会检查这个标记:- 如果为
true:执行渲染流程(更新场景状态 → 绘制图元 → 输出到画布),然后将标记置为false; - 如果为
false:跳过渲染,节省性能。
- 如果为
二、使用场景:什么时候需要调用?
1. 必须调用的场景(核心)
以下操作修改了场景,但 Cesium 无法自动检测,必须手动触发渲染:
// 示例1:手动修改自定义几何体的顶点数据
const primitive = viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.BoxGeometry({
vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
minimum: new Cesium.Cartesian3(-100000, -100000, -100000),
maximum: new Cesium.Cartesian3(100000, 100000, 100000)
})
}),
appearance: new Cesium.PerInstanceColorAppearance()
}));
// 手动修改几何体顶点(Cesium 无法感知这个修改)
primitive.geometryInstances.geometry.attributes.position.value[0] = 200000;
// 必须调用 requestRender() 才能看到修改后的效果
viewer.scene.requestRender();
// 示例2:自定义材质参数更新
const material = new Cesium.Material({
fabric: {
type: 'Color',
uniforms: {
color: new Cesium.Color(1, 0, 0, 1)
}
}
});
// 修改材质颜色(非 Cesium 自动触发的修改)
material.uniforms.color = new Cesium.Color(0, 1, 0, 1);
viewer.scene.requestRender(); // 触发渲染才能看到颜色变化
2. 不需要调用的场景(Cesium 自动处理)
以下操作 Cesium 会自动触发渲染,无需手动调用:
- 相机操作:
viewer.camera.flyTo()、viewer.camera.setView(); - 实体/图元增删:
viewer.entities.add()、viewer.scene.primitives.remove(); - 时间变化:
viewer.clock.tick()(Cesium 内部自动调用); - 交互操作:鼠标拖拽地球、缩放、旋转。
3. 进阶场景:批量修改后统一触发
如果有大量修改操作(比如循环修改1000个实体属性),不要每次修改都调用 requestRender(),而是批量修改完成后调用一次,避免性能浪费:
// 反例:性能差(触发1000次渲染请求)
for (let i = 0; i < 1000; i++) {
entities[i].position = new Cesium.Cartesian3(i * 1000, 0, 0);
viewer.scene.requestRender(); // 错误:频繁调用
}
// 正例:性能优(仅触发1次渲染请求)
for (let i = 0; i < 1000; i++) {
entities[i].position = new Cesium.Cartesian3(i * 1000, 0, 0);
}
viewer.scene.requestRender(); // 正确:批量修改后调用
三、进阶知识点:requestRender() 的细节
1. 重复调用的幂等性
多次调用 requestRender() 不会重复触发多次渲染,而是合并为一次:
// 连续调用3次,最终只会触发1次渲染
viewer.scene.requestRender();
viewer.scene.requestRender();
viewer.scene.requestRender();
原理:Cesium 内部会先检查「渲染请求标记」,如果已经是 true,则直接返回,不会重复标记。
2. 与 render() 的区别
requestRender():异步触发渲染(加入下一帧渲染队列),非阻塞,是推荐用法;scene.render():同步立即触发渲染,阻塞主线程,可能导致卡顿,仅在特殊场景(如截图)使用:// 截图场景(需要立即渲染最新状态) viewer.scene.requestRender(); // 标记需要渲染 viewer.scene.render(); // 立即执行渲染(确保截图是最新的) const canvas = viewer.canvas; const dataUrl = canvas.toDataURL('image/png'); // 获取截图
3. 禁用自动渲染后的手动控制
如果通过 scene.requestRenderMode = Cesium.RequestRenderMode.MANUAL 禁用自动渲染,所有渲染都必须手动调用 requestRender():
// 禁用自动渲染(仅在性能极度敏感场景使用)
viewer.scene.requestRenderMode = Cesium.RequestRenderMode.MANUAL;
viewer.scene.maximumRenderTimeChange = Infinity;
// 此时任何修改都需要手动触发渲染
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116, 39),
point: { pixelSize: 10 }
});
viewer.scene.requestRender(); // 必须调用才能看到实体
// 相机移动后也需要手动调用
viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(116, 39, 10000) });
viewer.scene.requestRender();
四、常见坑点与避坑指南
坑点1:修改自定义着色器/材质参数后没效果 → 忘记调用
requestRender();
✅ 解决:修改后立即调用requestRender()。坑点2:频繁调用导致性能下降 → 循环中每次修改都调用;
✅ 解决:批量修改后统一调用一次。坑点3:误以为
requestRender()是同步渲染 → 调用后立即截图得到旧画面;
✅ 解决:截图前先调用requestRender(),再调用scene.render()同步渲染。
总结
viewer.scene.requestRender()的核心作用是手动触发 Cesium 场景重新渲染,仅在 Cesium 无法自动感知修改时使用;- 最佳实践:批量修改后统一调用,避免频繁调用;重复调用不会重复渲染,无需担心;
- 区分
requestRender()(异步,推荐)和scene.render()(同步,仅特殊场景用),禁用自动渲染后必须手动调用。
书签篮