news 2026/7/11 19:29:17

Cesium 曲线漫游教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cesium 曲线漫游教程

曲线漫游 ·Curve Roam· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • Cesium3DTileset 加载 3D Tiles 倾斜摄影
  • Cesium Entity 高层实体 API
  • 3D Tiles 流式 LOD 场景
  • requestAnimationFrame渲染循环与resize自适应

效果说明

本案例演示曲线漫游效果:加载倾斜摄影或人工 3D Tiles 白膜并自动定位相机;核心用到 Cesium3DTileset、Cesium、3D。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Viewer聚合 Scene、Camera、Clock 与渲染循环,是 Cesium 应用入口。
  • Cesium3DTileset流式加载 LOD 瓦片,适合城市倾斜摄影;常用viewer.zoomTo(tileset)viewBoundingSphere定位。
  • Entity面向点线面/模型/标签的高层 API;与 Primitive 相比更适合交互与属性驱动。

实现步骤

  • 创建 Viewer,配置地形/影像(若案例需要)并设置初始相机
  • 异步加载模型 / 3D Tiles / GeoJSON 等资源并加入 scene 或 entities
  • requestAnimationFrame循环中更新状态并 render(Cesium 为viewer.render或自动渲染)
  • 代码要点

    import * as Cesium from 'cesium'

    import * as dat from 'dat.gui'

    const box = document.getElementById('box')

    const viewer = new Cesium.Viewer(box, {

    animation: false,//是否创建动画小器件,左下角仪表

    baseLayerPicker: false,//是否显示图层选择器,右上角图层选择按钮

    baseLayer: Cesium.ImageryLayer.fromProviderAsync(

    Cesium.ArcGisMapServerImageryProvider.fromUrl(GLOBAL_CONFIG.getLayerUrl()) ),

    fullscreenButton: false,//是否显示全屏按钮,右下角全屏选择按钮

    timeline: false,//是否显示时间轴

    infoBox: false,//是否显示信息框

    })

    const tileset = await Cesium.Cesium3DTileset.fromUrl(FILE_HOST + '3dtiles/house/tileset.json')

    viewer.scene.primitives.add(tileset)

    viewer.flyTo(tileset);

    // 经纬度 高度 const list = [ [121.47857119758791, 29.79125471709178, 16.455626729366145], [121.47888991686754, 29.79121144438129, 16.43945469952735], [121.4793563626501, 29.79115700403782, 16.500224202937577], [121.47959615722343, 29.791255451852457, 19.638183861734586], [121.4799150177678, 29.791206202923174, 19.709391069654206], [121.48017710101357, 29.791136574675704, 19.707021008968702], [121.48024839194412, 29.791355774130647, 16.498928502606283], [121.47938339181717, 29.791564467242317, 17.821189061225503], [121.4788135287918, 29.79168578787095, 19.667240655082814], [121.47901177358922, 29.791479635806983, 19.655729311572056] ]

    const cartesianPoints = list.map(item => Cesium.Cartesian3.fromDegrees(item[0], item[1], item[2] + 3))

    // CatmullRomSpline 插值 const catmullRomSpline = new Cesium.CatmullRomSpline({ points: cartesianPoints, times: cartesianPoints.map((_, index) => index / (cartesianPoints.length - 1)) })

    const numPoints = 1000 // 插值点数量 const interpolatedPoints = [] for (let i = 0; i < numPoints; i++) { const t = i / (numPoints - 1) const point = catmullRomSpline.evaluate(t) interpolatedPoints.push(point) }

    // 示例线路 viewer.entities.add({ name: '路线', polyline: { positions: interpolatedPoints, width: 1, material: Cesium.Color.YELLOW } })

    // 相机第一人称漫游 const flyControls = { active: false, speed: 2.5, position: 0, loop: true, start() { this.active = true; animate(); }, stop() { this.active = false; }, reset() { this.position = 0; } }

    // 简化的GUI控制面板 const gui = new dat.GUI() gui.add(flyControls, 'speed').name('速度') gui.add(flyControls, 'loop').name('循环') gui.add(flyControls, 'start').name('开始') gui.add(flyControls, 'stop').name('停止') gui.add(flyControls, 'reset').name('重置')

    // 动画函数 function animate() { if (!flyControls.active) return;

    flyControls.position += flyControls.speed / 10000;

    // 处理循环或结束 if (flyControls.position >= 1) { if (flyControls.loop) flyControls.position = 0; else return flyControls.active = false }

    // 计算当前位置和下一位置 const currentPos = catmullRomSpline.evaluate(flyControls.position); const nextT = flyControls.position + 0.01 >= 1 ? 0.01 : flyControls.position + 0.01; const nextPos = catmullRomSpline.evaluate(nextT);

    // 设置相机朝向 const direction = Cesium.Cartesian3.subtract(nextPos, currentPos, new Cesium.Cartesian3()) if (Cesium.Cartesian3.magnitude(direction) < 0.01) return requestAnimationFrame(animate); Cesium.Cartesian3.normalize(direction, direction)

    // 计算上方向(地球表面法向量) const up = Cesium.Cartesian3.normalize(Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(currentPos, new Cesium.Cartesian3()), new Cesium.Cartesian3())

    viewer.camera.setView({ destination: currentPos, orientation: { direction, up } })

    requestAnimationFrame(animate)

    }

    完整源码:GitHub

    小结

    • 本文提供曲线漫游完整 Cesium.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Cesium.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 19:28:42

Unity响应式UI设计:从锚点、Canvas Scaler到多设备适配的完整指南

1. 项目概述&#xff1a;为什么Unity响应式界面是开发者的必修课&#xff1f;如果你做过Unity项目&#xff0c;尤其是面向移动端或者PC、主机多平台的项目&#xff0c;一定会对一个问题深有感触&#xff1a;为什么在编辑器里排得漂漂亮亮的UI&#xff0c;换个分辨率或者设备就全…

作者头像 李华
网站建设 2026/7/11 19:28:19

C++ 数据结构课程设计实战:植物百科系统 21 关核心算法实现与性能分析

C 数据结构课程设计实战&#xff1a;植物百科系统21关核心算法实现与性能优化全解析在计算机科学教育中&#xff0c;数据结构与算法是构建高效程序的基石。本文将深入剖析一个完整的植物百科管理系统&#xff0c;通过21个关键关卡的设计与实现&#xff0c;展示C在数据结构课程设…

作者头像 李华
网站建设 2026/7/11 19:27:50

Tomcat 10.1.7 Windows 环境变量配置:3个关键变量与8080端口访问测试

Tomcat 10.1.7 Windows环境配置全指南&#xff1a;从变量设置到端口调优 环境变量配置的底层逻辑与实战 在Windows系统中配置Tomcat环境变量绝非简单的路径添加&#xff0c;而是搭建Java Web开发环境的基础工程。CATALINA_HOME作为Tomcat的根目录变量&#xff0c;其作用范围贯…

作者头像 李华
网站建设 2026/7/11 19:27:50

433M 遥控信号协议逆向:从示波器波形到 0x55AAFF 数据解析

433MHz遥控信号逆向工程实战&#xff1a;从示波器波形到数据帧解析1. 认识433MHz无线通信系统在智能家居和物联网设备中&#xff0c;433MHz频段因其穿透性强、传输距离远的特点成为遥控系统的首选。不同于2.4GHz频段的复杂协议栈&#xff0c;433MHz通信通常采用简单的ASK/OOK调…

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

STM32F103 多传感器融合设计:红外对管+湿度传感器+LCD1602 3模块联调指南

STM32F103多传感器融合实战&#xff1a;红外对管湿度传感器LCD1602联调全解析引言在嵌入式系统开发中&#xff0c;多传感器数据融合是一个极具挑战性的课题。当红外对管、湿度传感器和LCD显示屏三大模块需要在STM32F103平台上协同工作时&#xff0c;开发者将面临中断冲突、资源…

作者头像 李华
网站建设 2026/7/11 19:26:55

微利时代下制造业车间管理的挑战与应对策略

引言&#xff1a;制造业面临的新常态在当今市场环境下&#xff0c;产品品种日益增多&#xff0c;生命周期却越来越短。生产部门面临着前所未有的压力&#xff1a;客户要求更短、更准时的交货期&#xff0c;同时期望更低的价格和更高的质量。制造业的竞争&#xff0c;归根结底是…

作者头像 李华