当前位置: 首页 > news >正文

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 开源仓库
http://www.jsqmd.com/news/1169252/

相关文章:

  • DiffSinger:5分钟快速上手的AI歌声合成终极指南
  • 洛雪音乐音源终极指南:免费获取全网最新音乐资源
  • 为什么选择openEuler Raspberry Pi Kernel:10个树莓派开发者必须知道的优势
  • AI辅助合规审计:自动检查数据库配置是否满足等保和GDPR要求
  • 实验7-3 自媒体运营可视化探索
  • ZFX山海证券外汇:围绕规范化意识与用户体验路径的清单评估
  • Hadoop 2.6.5 伪分布式环境配置:3个核心配置文件修改与端口9000避坑指南
  • 5步让老Mac焕发新生:OpenCore Legacy Patcher终极指南
  • 从零手搓 Linux 容器网络:跟着 Ivan Velichko 跑通 netns → veth → bridge → NAT 全链路
  • 并发控制3大协议实战对比:从2PL到MVCC的隔离级别演进
  • Windows系统中的Git基本操作命令使用教程
  • PyTorch 2.12 Tensor 创建全解析:5种方法对比与3个性能陷阱
  • Cursor API 配置失效全链路诊断指南(从VS Code插件到AI模型上下文传递的7层验证)
  • LV3296与PIC18LF4685嵌入式数据采集系统设计
  • 6款高效降AIGC网站 降痕效果拉满 - 降AI小能手
  • 高精度ADC ADS127L11与PIC18F66K40的工业数据采集方案
  • HarmonyKit | 鸿蒙开发:DevEco Studio 编译调试与性能优化
  • 2026深圳福田区本地正规空调拆装服务商全盘点,合规资质认证机构实力对比,避坑指南及高口碑可对接商家推荐 - 深圳家顺兴搬家
  • 工业绿色生命:01 绿色自动化是谁?从节能到碳足迹全生命周期
  • DeepSeek V4 Pro以95.19分居首:2026-07-08 Smoke快测数据简报
  • 2026年AI量化工具怎么选,先定位学习开发还是执行
  • Navicat重置脚本终极指南:如何在Mac上实现数据库工具无限试用
  • 数据库并发控制3大方案对比:悲观锁、乐观锁与MVCC在10万QPS下的性能差异
  • 07-Python 输入 input 输入数据类型转换
  • 多件闲置奢侈品一同出手,哪种回收方式收益与安全更有保障? - 讯息早知道
  • UE4随机数高效使用指南:从FMath::RandRange到FRandomStream实战
  • 15分钟搞定黑苹果:OpCore-Simplify图形化EFI配置终极指南
  • 2026年7月最新成都帝舵官方售后客服服务电话及地址网点大全 - 帝舵中国官方服务中心
  • Java面试前需要掌握的三个关键知识点
  • 从$0.002到$0.021/千Token:DeepSeek不同模型价格跃迁图谱与选型决策树