尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Cesium与SuperMap三维智慧城市落地实战:架构、对接与避坑指南
简介这是一套面向三维WebGIS开发者与智慧城市项目实践者的Cesium三维可视化工程兼容超图SuperMap在线三维服务适合具备一定前端与WebGL基础、希望快速搭建三维城市场景的读者参考。工程内含智慧城市、警情模拟、水积警情模拟三个独立场景每个HTML对应一个可运行示例可直接在VSCode或HBuilder中打开调试所有3D模型均已内置无需额外下载。压缩包共约2000个文件涵盖png、jpg贴图js脚本css样式json配置以及s3m、gltf、glb等三维模型与地形、KML数据整体约202.4MB目录中Build、examples与city系列脚本分工明确便于按模块查阅。目前已有2355人学习下载读者可借此掌握Cesium场景搭建、超图服务对接与警情、积水等专题模拟的实现思路快速复用到自己的三维城市项目中。1. 三维智慧城市项目从 Cesium 到 SuperMap 的完整落地路径很多做三维 WebGIS 的开发者都遇到过这个场景客户要求大屏上跑一个城市级三维场景建筑白模、路网、水系、管线全都要还得能对接已有的 GIS 平台服务。你打开 Cesium 官方示例加载个全球地形没问题但一旦换成国内某测绘院提供的三维服务地址要么跨域要么坐标系对不上要么瓦片层级错乱。这个项目就是冲着这类需求去的——基于 Cesium 构建一套三维智慧城市系统同时兼容 SuperMap 的三维服务接口。它适合两类人一是手里有三维数据、需要快速搭出可视化平台的 GIS 开发二是想学 Cesium 与国内 GIS 平台对接的 WebGL 前端。源码结构清晰跑起来之后能直接看到城市级三维场景改起来也有明确的模块边界。2. 技术选型与架构拆解为什么是 Cesium 加 SuperMap 的组合2.1 三维渲染层为什么锁定 CesiumCesium 在三维 WebGL 领域的位置不用多说真正让这个项目选它的原因有三个。第一它对 3D Tiles 的支持最成熟城市级建筑白模动辄几十万面片用 3D Tiles 分块加载才能保证帧率。第二Cesium 的相机控制和场景图 API 足够开放智慧城市常见的飞行漫游、图层显隐、点击查询都能直接操作 Viewer 和 Scene 对象。第三它原生支持 WGS84 和 Web Mercator 两套坐标系和国内 GIS 数据对接时少一层转换。项目里 Cesium 的引入方式不是 npm 包而是静态资源目录下的构建版本。这样做的好处是部署简单不需要前端构建工具也能跑代价是版本升级要手动替换。常见做法是在index.html里通过script标签引入Cesium.js然后设置window.CESIUM_BASE_URL指向Build/Cesium目录否则 Worker 和 Assets 加载会 404。!-- index.html 中 Cesium 的引入方式 -- script src./Cesium/Cesium.js/script script // 必须设置否则 Cesium 内部的 Worker、Assets 路径会解析错误 window.CESIUM_BASE_URL ./Cesium/; /script这里的关键参数是CESIUM_BASE_URL它决定了 Cesium 运行时去哪里找Workers、Assets、Widgets这些目录。如果你用 webpack 打包通常用copy-webpack-plugin把这些目录拷到输出目录再配合DefinePlugin注入这个变量。项目里直接静态引入省去了构建配置适合快速验证和二次开发。2.2 SuperMap 三维服务的对接方式SuperMap 的三维服务通常以 iServer 为发布端提供 REST 风格的三维瓦片、地形、模型服务。Cesium 本身不认识 SuperMap 的私有协议所以项目里做了一层适配。核心思路是把 SuperMap 的三维服务地址当作 Cesium 的UrlTemplateImageryProvider或Cesium3DTileset的数据源通过重写requestImage或直接拼接瓦片 URL 来加载。// 对接 SuperMap 三维瓦片服务的典型写法 const superMapProvider new Cesium.UrlTemplateImageryProvider({ // SuperMap iServer 三维瓦片服务地址模板 url: http://localhost:8090/iserver/services/3D-City/rest/realspace/datas/city/tiles/{z}/{x}/{y}.png, // 指定坐标系SuperMap 常用 4326 或 3857 tilingScheme: new Cesium.GeographicTilingScheme(), // 最大层级要和 SuperMap 发布时一致否则会出现瓦片错位 maximumLevel: 18, // 关闭 Cesium 默认的瓦片裁剪避免边缘黑边 rectangle: Cesium.Rectangle.fromDegrees(116.0, 39.0, 117.0, 40.0) }); viewer.imageryLayers.addImageryProvider(superMapProvider);这段代码里tilingScheme和maximumLevel是两个最容易翻车的参数。SuperMap 发布三维服务时如果用的是地理坐标系这里就必须用GeographicTilingScheme如果发布的是投影坐标系得换成WebMercatorTilingScheme。maximumLevel对不上瓦片要么加载不出来要么层级混乱。rectangle参数用来限定加载范围城市级项目不加这个Cesium 会尝试请求全球瓦片直接拖垮浏览器。2.3 整体架构分层项目在结构上分了三层数据服务层、三维渲染层、业务交互层。数据服务层负责和 SuperMap iServer 通信获取三维瓦片、地形、属性数据三维渲染层就是 Cesium Viewer 和场景管理业务交互层处理点击查询、图层控制、飞行定位这些操作。目录结构大致如下project/ ├── Cesium/ # Cesium 静态资源 ├── src/ │ ├── core/ # 核心初始化逻辑 │ │ ├── viewer.js # Viewer 创建与配置 │ │ └── layerManager.js # 图层管理 │ ├── services/ # 服务对接 │ │ ├── supermap.js # SuperMap 服务封装 │ │ └── terrain.js # 地形服务 │ ├── interaction/ # 交互逻辑 │ │ ├── pick.js # 点击拾取 │ │ └── flyTo.js # 飞行定位 │ └── main.js # 入口 ├── index.html └── assets/ # 图标、样式这种分层的好处是换掉 SuperMap 换成别的 GIS 平台只需要改services/目录换掉 Cesium 换成别的渲染引擎只需要改core/和interaction/。对于二次开发来说边界清晰不会牵一发动全身。3. 跑起来环境准备与三维场景初始化3.1 本地环境与依赖检查项目本身是纯前端静态资源不需要 Node.js 构建但需要一个本地 HTTP 服务来跑因为 Cesium 的 Worker 和三维瓦片请求都不支持file://协议。最省事的方式是用 Python 自带的 HTTP 服务# 在项目根目录执行默认监听 8000 端口 python -m http.server 8000如果你机器上有 Node.js也可以用npx serve或http-server。注意端口不要和 SuperMap iServer 冲突iServer 默认是 8090。启动后浏览器访问http://localhost:8000如果页面白屏先打开控制台看有没有CESIUM_BASE_URL相关的 404。提示Cesium 的静态资源目录必须和CESIUM_BASE_URL指向一致否则会出现「Viewer 初始化了但地球不显示」的情况。3.2 Viewer 初始化与场景配置Viewer 是整个三维场景的容器项目里对它的配置做了封装方便统一管理。// src/core/viewer.js export function createViewer(containerId) { const viewer new Cesium.Viewer(containerId, { // 关闭不需要的默认控件减少干扰 animation: false, timeline: false, baseLayerPicker: false, geocoder: false, homeButton: false, sceneModePicker: false, navigationHelpButton: false, // 使用自定义影像不用 Cesium 默认的 Bing 地图 imageryProvider: false, // 开启地形但地形服务地址在外部注入 terrainProvider: new Cesium.EllipsoidTerrainProvider(), // 关闭抗锯齿城市级场景下性能优先 contextOptions: { webgl: { antialias: false } } }); // 隐藏 Cesium 默认的版权信息条 viewer.cesiumWidget.creditContainer.style.display none; // 开启深度检测保证建筑和地形的遮挡关系正确 viewer.scene.globe.depthTestAgainstTerrain true; // 设置初始视角定位到城市范围 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(116.5, 39.9, 5000), orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-45), roll: 0 } }); return viewer; }这里有几个参数值得展开。imageryProvider: false是为了避免 Cesium 默认去请求 Bing 地图国内网络环境下大概率超时。depthTestAgainstTerrain开启后建筑模型会被地形正确遮挡但代价是渲染开销增加如果场景里地形起伏不大可以关掉换性能。contextOptions.webgl.antialias关掉抗锯齿在 4K 大屏上可能有点锯齿但帧率能提升不少智慧城市大屏通常更看重流畅度。3.3 加载 SuperMap 三维服务与地形Viewer 创建好之后下一步是把 SuperMap 的三维瓦片和地形挂上去。项目里把这一步单独放在services/supermap.js中。// src/services/supermap.js export function addSuperMap3DLayer(viewer, options) { const { url, maximumLevel, rectangle } options; // 三维瓦片服务 const imageryProvider new Cesium.UrlTemplateImageryProvider({ url: url, tilingScheme: new Cesium.GeographicTilingScheme(), maximumLevel: maximumLevel || 18, rectangle: rectangle ? Cesium.Rectangle.fromDegrees(...rectangle) : undefined }); viewer.imageryLayers.addImageryProvider(imageryProvider); // 如果 SuperMap 同时发布了地形服务用 CesiumTerrainProvider 加载 if (options.terrainUrl) { viewer.terrainProvider new Cesium.CesiumTerrainProvider({ url: options.terrainUrl, // 请求地形顶点法线用于光照计算 requestVertexNormals: true }); } return imageryProvider; }调用的时候传入 SuperMap iServer 发布出来的服务地址。requestVertexNormals这个参数如果地形服务支持开启后建筑和地形的光照会更自然但会增加数据传输量。城市级项目里如果地形起伏不大可以关掉。加载完成后如果发现瓦片位置偏移优先检查tilingScheme和 SuperMap 发布时选的坐标系是否一致。这是最常见的对接问题没有之一。4. 核心模块拆解图层管理、点击拾取与飞行定位4.1 图层管理器的设计与实现智慧城市项目里图层数量多建筑、道路、水系、管线、标注每个都要能独立控制显隐和顺序。项目里用layerManager统一管理。// src/core/layerManager.js export class LayerManager { constructor(viewer) { this.viewer viewer; this.layers new Map(); // key: layerId, value: { type, layer } } // 添加影像图层 addImageryLayer(id, provider) { const layer this.viewer.imageryLayers.addImageryProvider(provider); this.layers.set(id, { type: imagery, layer }); return layer; } // 添加 3D Tiles 图层 async add3DTilesLayer(id, url) { const tileset await Cesium.Cesium3DTileset.fromUrl(url, { // 最大屏幕空间误差值越小越精细性能开销越大 maximumScreenSpaceError: 16, // 开启动态屏幕空间误差根据帧率自动调整 dynamicScreenSpaceError: true, // 跳过细节层次加速加载 skipLevelOfDetail: true }); this.viewer.scene.primitives.add(tileset); this.layers.set(id, { type: 3dtiles, layer: tileset }); return tileset; } // 控制显隐 setVisible(id, visible) { const item this.layers.get(id); if (!item) return; if (item.type imagery) { item.layer.show visible; } else { item.layer.show visible; } } // 移除图层 remove(id) { const item this.layers.get(id); if (!item) return; if (item.type imagery) { this.viewer.imageryLayers.remove(item.layer); } else { this.viewer.scene.primitives.remove(item.layer); } this.layers.delete(id); } }maximumScreenSpaceError是 3D Tiles 加载的核心参数默认 16调小到 8 会更精细但帧率下降明显调到 32 适合大屏远观。dynamicScreenSpaceError开启后 Cesium 会根据当前帧率动态调整这个值城市级场景建议开启。skipLevelOfDetail在快速移动相机时能跳过中间层级减少卡顿但静止时可能看到模型突然变精细看项目取舍。4.2 点击拾取与属性查询点击建筑弹出属性面板是智慧城市的标配功能。Cesium 提供了Scene.pick方法但直接拿到的对象需要区分是 3D Tiles 还是普通实体。// src/interaction/pick.js export function initPick(viewer, onPick) { const handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction((movement) { // 获取点击位置的拾取对象 const picked viewer.scene.pick(movement.position); if (!picked) { onPick(null); return; } // 3D Tiles 的拾取结果包含 getProperty 方法 if (picked instanceof Cesium.Cesium3DTileFeature) { const properties {}; const propertyIds picked.getPropertyIds(); propertyIds.forEach((id) { properties[id] picked.getProperty(id); }); onPick({ type: 3dtiles, properties }); return; } // 普通 Entity 的拾取结果 if (picked.id instanceof Cesium.Entity) { onPick({ type: entity, entity: picked.id }); return; } onPick(null); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); }这里的关键是区分Cesium3DTileFeature和Entity。3D Tiles 的属性通过getProperty逐个读取Entity 则直接拿id。实际项目里建筑白模通常用 3D Tiles属性存在瓦片的 batch table 里而标注、点位用 Entity 更灵活。ScreenSpaceEventHandler记得在组件销毁时调用handler.destroy()否则多次初始化会导致点击事件重复触发。4.3 飞行定位与相机控制飞行定位用于从列表点击某个建筑后相机平滑飞到目标位置。// src/interaction/flyTo.js export function flyToFeature(viewer, target) { // target 可以是 Entity、3D Tiles 的包围盒中心或经纬度坐标 if (target instanceof Cesium.Entity) { viewer.flyTo(target, { duration: 2, // 飞行时间秒 offset: new Cesium.HeadingPitchRange( 0, Cesium.Math.toRadians(-30), 500 // 距离目标 500 米 ) }); return; } // 如果是经纬度坐标 viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees( target.longitude, target.latitude, target.height || 1000 ), orientation: { heading: Cesium.Math.toRadians(target.heading || 0), pitch: Cesium.Math.toRadians(target.pitch || -45), roll: 0 }, duration: 2 }); }offset里的HeadingPitchRange控制相机相对目标的方位角和俯仰角range是距离。飞行时间duration设成 2 秒比较自然太短会晕太长用户等不及。如果目标是一个 3D TilesetflyTo会自动计算包围盒但有时候包围盒太大飞过去之后建筑很小这时候需要手动指定offset的range。5. 避坑与排查对接 SuperMap 三维服务时最容易翻车的几个点5.1 瓦片错位或层级混乱现象加载 SuperMap 三维瓦片后地图位置整体偏移或者放大到某一层级后瓦片突然错乱。原因tilingScheme和 SuperMap 发布服务时选的坐标系不一致。SuperMap iServer 发布三维服务时如果数据是地理坐标系如 CGCS2000必须用GeographicTilingScheme如果是投影坐标系如 Web Mercator必须用WebMercatorTilingScheme。另外maximumLevel如果大于 SuperMap 实际发布的层级Cesium 会请求不存在的瓦片导致空白或错位。解决先确认 SuperMap 服务的坐标系和最大层级再对应设置 Cesium 的参数。可以在浏览器开发者工具的网络面板里看瓦片请求的 URL如果返回 404 或图片尺寸不对基本就是这两个参数的问题。5.2 跨域请求被拦截现象控制台报CORS policy错误瓦片和地形都加载不出来。原因SuperMap iServer 默认没有开启跨域头而 Cesium 的请求是跨域请求。解决在 iServer 的配置里开启 CORS或者在前端加一层代理。开发阶段可以用http-server的--cors参数生产环境建议在 Nginx 里配置Access-Control-Allow-Origin。注意不要用*指定具体域名更安全。5.3 地形与建筑穿插现象建筑模型一半埋在地形下面一半露出来。原因depthTestAgainstTerrain没有开启或者地形服务和建筑模型的坐标系不一致。解决开启viewer.scene.globe.depthTestAgainstTerrain true。如果开启后仍然穿插检查地形服务和建筑模型是否用了同一套坐标系。常见做法是地形用 SuperMap 发布的地形服务建筑用 3D Tiles两者都基于同一坐标系发布。5.4 内存泄漏与帧率下降现象运行一段时间后浏览器内存飙升帧率从 60 掉到 20 以下。原因图层反复添加移除没有释放或者 3D Tiles 的缓存没有清理。解决移除图层时调用viewer.scene.primitives.remove并置空引用3D Tiles 可以设置tileset.maximumMemoryUsage限制内存占用默认是 512MB城市级项目可以调到 1024MB 或更高但要注意机器配置。另外ScreenSpaceEventHandler在页面切换时一定要destroy。5.5 飞行定位后相机失控现象调用flyTo后相机飞到了奇怪的位置或者飞行结束后无法手动控制。原因flyTo的offset参数设置不当或者飞行过程中用户手动操作了相机导致冲突。解决飞行前先viewer.camera.cancelFlight()飞行时给duration设一个合理值不要设成 0 或负数。如果飞行后相机无法控制检查是否有其他代码在持续修改相机位置比如自动旋转或漫游逻辑没有正确停止。6. 二次开发与改造从能跑到好用的几个关键动作项目跑起来之后二次开发的空间主要在三个方向数据源替换、交互增强、性能调优。数据源替换是最常见的需求。如果客户用的是另一家 GIS 平台的三维服务只需要改services/supermap.js里的 URL 拼接逻辑和tilingScheme配置。我一般会把这部分抽成一个适配器接口不同平台实现不同的getImageryProvider和getTerrainProvider方法上层业务代码不用动。// 适配器模式的改造思路 class GISServiceAdapter { getImageryProvider(options) { throw new Error(必须实现 getImageryProvider); } getTerrainProvider(options) { throw new Error(必须实现 getTerrainProvider); } } class SuperMapAdapter extends GISServiceAdapter { getImageryProvider(options) { return new Cesium.UrlTemplateImageryProvider({ url: options.url, tilingScheme: new Cesium.GeographicTilingScheme(), maximumLevel: options.maximumLevel }); } getTerrainProvider(options) { return new Cesium.CesiumTerrainProvider({ url: options.terrainUrl, requestVertexNormals: true }); } }这样换平台的时候只需要新增一个XXXAdapter在入口处切换实例即可。验证方法也很直接把SuperMapAdapter换成新的适配器跑一遍加载、点击、飞行三个核心流程看有没有报错和位置偏移。交互增强方面项目目前只有点击拾取和飞行定位。实际智慧城市项目通常还需要框选查询、图层叠加分析、动态效果如管线流动、预警闪烁。这些都可以在interaction/目录下新增模块通过事件总线或回调函数和主流程解耦。我一般会用一个简单的发布订阅模式避免模块之间直接引用。性能调优是城市级项目的必修课。除了前面提到的maximumScreenSpaceError和maximumMemoryUsage还可以做几件事一是用Cesium.RequestScheduler限制并发请求数避免一次性请求太多瓦片二是对远处的建筑做裁剪只加载相机视野范围内的 3D Tiles三是把不常看的图层做成按需加载而不是一开始就全部挂上去。// 限制并发请求数避免浏览器被瓦片请求打满 Cesium.RequestScheduler.maximumRequests 50; Cesium.RequestScheduler.maximumRequestsPerServer 20;这两个参数在瓦片服务响应慢的时候特别有用默认值偏高城市级场景下调小一点能明显改善卡顿。从那以后我每次对接新的三维服务都强制先跑一遍「坐标系确认 → 层级对齐 → 跨域检查 → 小范围加载」这四步确认没问题再全量挂图层。很多翻车都是因为跳过了其中某一步等到场景全加载出来才发现问题排查成本翻倍。希望这些经验能帮到你源码跑起来之后先从替换一个图层开始改比一上来就动核心逻辑要稳得多。本文还有配套的精品资源点击获取
RELATED

相关推荐

Python深度强化学习云工作流调度器实战

Python深度强化学习云工作流调度器实战

简介:本资源是一套高分毕业设计项目——基于Python深度强化学习的云工作流调度系统完整实现,面向计算机、人工智能、软件工程等专业本科生及研究生,解决云环境中DAG任务动态调度优化这一典型NP难问题。项目融合图神经网络建模有向无环图结构、…

📅 2026/10/25 10:20:04
基于Transformer的聊天机器人源码解析:从编码器-解码器到训练避坑

基于Transformer的聊天机器人源码解析:从编码器-解码器到训练避坑

简介:基于Transformer架构的聊天机器人源码包,面向自然语言处理初学者与Python开发人员,输入日常中文文本后,系统即可自动生成语义相关的应答,可用于智能客服、闲聊陪伴等场景。压缩包共367个文件,以308个P…

📅 2026/10/25 10:20:04
Claude Opus与Sonnet风格差异的本质:提示词的模型级翻译机制

Claude Opus与Sonnet风格差异的本质:提示词的模型级翻译机制

1. 这不是模型“能力差异”,而是提示词被不同模型“翻译”成了两种语言你有没有试过,把同一句中文指令发给两个不同口音的翻译官?比如让一位上海老克勒和一位广州粤语主播,同时把“请用轻松幽默的方式介绍下最近爆火的AI视频生成技…

📅 2026/10/25 10:20:04
MORE NEWS

更多资讯

📰

spooling假脱机输入输出模拟技术:Python实现打印队列与优先级调度

简介:这份资源是面向操作系统课程学习者与计算机专业学生的Spooling假脱机输入输出模拟技术实践包,围绕联机外围设备同时操作原理,用两个请求输出进程与一个spooling输出进程的进程模型,演示如何借助磁盘缓冲区把慢速I/O设备虚拟化…

📰

BIRT运行时4.8.0部署实战:从解压到验证的完整指南

简介:BIRT(Business Intelligence and Reporting Tools)是Eclipse基金会维护的开源报表系统,这份运行时环境包面向需要在Java Web项目中集成动态数据报表的开发者,尤其适合已具备一定Java Web基础、希望快速搭建报表服…

📰

CozyClay motion3编译器原理:浏览器内的FK/IK数学,150毫秒烤出730帧

【免费下载链接】CozyClay Open source previs software in the browser: block a scene, pose characters, author camera moves and cuts, then take the same shots to an AI video model. 项目地址: https://gitcode.com/gh_mirrors/co/CozyClay 点击查看 免费下…

📰

10天两个补丁!Home Assistant 2026.10 升级翻车实录:新卡片好看,自动化先罢工了

10天两个补丁!Home Assistant 2026.10 升级翻车实录:新卡片好看,自动化先罢工了 【免费下载链接】core :house_with_garden: Open source home automation that puts local control and privacy first. 项目地址: https://gitcode.com/GitH…

📰

只读MCP如何实时抓取任意网站?Inspo study()的SSRF防护完整指南

【免费下载链接】inspo Real websites for your coding agent to learn design from, searchable over MCP. 项目地址: https://gitcode.com/gh_mirrors/ins/inspo 点击查看 免费下载 Inspo 是一个为编码 Agent 提供"真实网站设计档案"的 MCP 服务器&…

📰

MATLAB生成与量化分析斑马图:图像伪影诊断实战

简介:本资源是一份面向雷达系统工程师与信号处理方向研究生的MATLAB实战工具包,聚焦PRF(脉冲重复频率)设计中的距离模糊与方位模糊分析问题。斑马图作为雷达参数权衡的关键可视化手段,能直观揭示不同PRF设置下模糊区域…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬