Vue.js - 集成Cesium构建三维可视化场景教程8(加载官方Ion 3D Tiles)
作者:hangge | 2026-07-13 09:14
如果说 Entity(实体)是场景中的“点缀”,那么 3D Tiles 就是场景的“骨架”。无论是城市级别的白模、高精度的倾斜摄影,还是复杂的 BIM 建筑模型,都是通过 3D Tiles 技术呈现在浏览器中的。下面我将通过样例演示如何创建 3D Tiles 实例并添加到场景中。

(2)运行效果如下,可以看到地图上会自动加载北京周边的 3D 建筑白模,缩放时可明显看到 LOD 切换,并且建筑数量随视野动态变化。

(2)运行效果如下:


(2)只显示全球建筑白模 3D Tiles 数据效果如下:
八、加载 Ion 3D Tiles
1,基本介绍
(1)3D Tiles 是用于流式传输大规模异构 3D 地理空间数据集的开放规范,由 Cesium 团队创建并已成为 OGC 社区标准。它支持海量三维模型、点云、摄影测量数据的可视化。
(2)3D Tiles 的核心逻辑是 LOD(分级细节):
- 远景:加载低分辨率的切片。
- 近景:加载高分辨率的切片。
- 结构:由一个 tileset.json 文件作为入口,索引众多的 .b3dm、.i3dm 或 .pnts 文件。
(3)3D Tiles 支持按需流式加载、细粒度裁剪和样式化。对大型三维可视化场景(城市级/园区级)非常重要,能显著减少首屏加载量并保证交互流畅。

2,加载全球建筑白模样例
(1)Cesium 官方提供了许多 3D Tiles 资产,其中最经典的就是 Cesium OSM Buildings(全球建筑白模),下面代码我们就是用该资产为例进行演示。
<template>
<div class="layer-container">
<div ref="cesiumContainer" class="cesium-container"></div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-overlay">
<div class="loading-spinner"></div>
<p>加载三维场景中...</p>
</div>
</div>
</template>
<script>
// 引入 Cesium 核心类
import * as Cesium from "cesium";
export default {
name: 'CesiumViewer',
data() {
return {
viewer: null,
loading: true,
terrainEnabled: true,
sampleEntities: [],
longitude: '',
latitude: '',
height: '',
}
},
mounted() {
// 确保 Cesium 已加载
if (typeof Cesium === 'undefined') {
console.error('Cesium 未加载,请检查配置')
this.loading = false
return
}
// 初始化 Cesium 场景
this.initCesium()
},
beforeDestroy() {
// 组件销毁时清理资源
this.destroyCesium()
},
methods: {
// 初始化 Cesium
async initCesium() {
try {
// 配置 Cesium 访问令牌
//Cesium.Ion.defaultAccessToken = '你的token'
// 创建 Viewer 实例
this.viewer = new Cesium.Viewer(this.$refs.cesiumContainer, {
animation: false, // 是否显示动画控件
baseLayerPicker: false, // 是否显示图层选择控件
fullscreenButton: false, // 是否显示全屏按钮
geocoder: false, // 是否显示地理编码搜索控件
homeButton: false, // 是否显示Home按钮
infoBox: false, // 是否显示信息框
sceneModePicker: false, // 是否显示3D/2D选择器
selectionIndicator: false, // 是否显示选取指示器组件
timeline: false, // 是否显示时间轴
navigationHelpButton: false, // 是否显示帮助按钮
scene3DOnly: true, // 每个几何实例仅以3D渲染以节省GPU内存
shouldAnimate: true, // 自动播放动画
// 地形配置
terrainProvider: await Cesium.createWorldTerrainAsync()
})
// 强制重新计算画布尺寸
this.viewer.canvas.width = this.viewer.container.clientWidth;
this.viewer.canvas.height = this.viewer.container.clientHeight;
this.viewer.resize(); // 核心方法:告知 Cesium 容器大小已变
// 加载 Cesium Ion 3D Tiles(全球建筑白模)
const tileset = await Cesium.createOsmBuildingsAsync()
this.viewer.scene.primitives.add(tileset)
// 设置初始视图
this.setInitialView()
// 加载完成
this.loading = false
console.log('Cesium 场景初始化完成')
} catch (error) {
console.error('初始化 Cesium 失败:', error)
this.loading = false
}
},
// 设置初始视图
setInitialView() {
// 设置初始位置(例如:北京天安门)
const initialPosition = Cesium.Cartesian3.fromDegrees(116.3974, 39.9093, 1500)
this.viewer.camera.setView({
destination: initialPosition,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
}
})
},
// 销毁 Cesium 资源
destroyCesium() {
if (this.viewer) {
this.viewer.destroy()
this.viewer = null
}
}
}
}
</script>
<style scoped>
.layer-container {
position: relative;
width: 100%;
height: 100%;
}
.cesium-container {
width: 100%;
height: 100%;
}
.loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1000;
color: white;
}
.loading-spinner {
border: 4px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 4px solid #42b983;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
(2)运行效果如下,可以看到地图上会自动加载北京周边的 3D 建筑白模,缩放时可明显看到 LOD 切换,并且建筑数量随视野动态变化。

(3)按下鼠标中键然后拖动改变视角,可以看地更明显些。

3,加载墨尔本摄影测量数据
(1)下面代码我们使用 Cesium.Cesium3DTileset.fromUrl 加载墨尔本摄影测量的 3D Tiles 数据,该数据集完整表示了墨尔本市范围内的所有物理要素,包括建筑物、树木以及地形。
<template>
<div class="layer-container">
<div ref="cesiumContainer" class="cesium-container"></div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-overlay">
<div class="loading-spinner"></div>
<p>加载三维场景中...</p>
</div>
</div>
</template>
<script>
// 引入 Cesium 核心类
import * as Cesium from "cesium";
export default {
name: 'CesiumViewer',
data() {
return {
viewer: null,
loading: true,
terrainEnabled: true,
sampleEntities: [],
longitude: '',
latitude: '',
height: '',
}
},
mounted() {
// 确保 Cesium 已加载
if (typeof Cesium === 'undefined') {
console.error('Cesium 未加载,请检查配置')
this.loading = false
return
}
// 初始化 Cesium 场景
this.initCesium()
},
beforeDestroy() {
// 组件销毁时清理资源
this.destroyCesium()
},
methods: {
// 初始化 Cesium
async initCesium() {
try {
// 配置 Cesium 访问令牌
Cesium.Ion.defaultAccessToken = '你的token'
// 创建 Viewer 实例
this.viewer = new Cesium.Viewer(this.$refs.cesiumContainer, {
animation: false, // 是否显示动画控件
baseLayerPicker: false, // 是否显示图层选择控件
fullscreenButton: false, // 是否显示全屏按钮
geocoder: false, // 是否显示地理编码搜索控件
homeButton: false, // 是否显示Home按钮
infoBox: false, // 是否显示信息框
sceneModePicker: false, // 是否显示3D/2D选择器
selectionIndicator: false, // 是否显示选取指示器组件
timeline: false, // 是否显示时间轴
navigationHelpButton: false, // 是否显示帮助按钮
scene3DOnly: true, // 每个几何实例仅以3D渲染以节省GPU内存
shouldAnimate: true, // 自动播放动画
// 地形配置
terrainProvider: await Cesium.createWorldTerrainAsync()
})
// 强制重新计算画布尺寸
this.viewer.canvas.width = this.viewer.container.clientWidth;
this.viewer.canvas.height = this.viewer.container.clientHeight;
this.viewer.resize(); // 核心方法:告知 Cesium 容器大小已变
// 加载墨尔本摄影测量数据
const tileset = await Cesium.Cesium3DTileset.fromUrl('https://tiles.arcgis.com/tiles/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Utrecht_3D_Tiles_Integrated_Mesh/3DTilesServer/tileset.json')
this.viewer.scene.primitives.add(tileset)
this.viewer.zoomTo(tileset)
// 加载完成
this.loading = false
console.log('Cesium 场景初始化完成')
} catch (error) {
console.error('初始化 Cesium 失败:', error)
this.loading = false
}
},
// 销毁 Cesium 资源
destroyCesium() {
if (this.viewer) {
this.viewer.destroy()
this.viewer = null
}
}
}
}
</script>
<style scoped>
.layer-container {
position: relative;
width: 100%;
height: 100%;
}
.cesium-container {
width: 100%;
height: 100%;
}
.loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1000;
color: white;
}
.loading-spinner {
border: 4px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 4px solid #42b983;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
(2)运行效果如下:


附一:加载我们自己的 Cesium Ion 3D Tiles
(1)Cesium 官方提供的 3D Tiles 资源可能并不能完全满足我们的需求,我们可以制作自己的 3D Tiles。首先上传数据到 Ion,我们可以上传数据到 Ion,包括:
- 倾斜摄影(OSGB / OBJ / FBX)
- BIM(IFC)
- GLB / Gltf
- 点云(LAS / LAZ)

(2)Cesium Ion 会自动进行如下一些列操作:
- 将其转换为 3D Tiles
- 生成生成 LOD
- 提供 Asset ID
(3)最后我们代码中通过 Asset ID (例如下面的 123456)加载进来即可。
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(123456) viewer.scene.primitives.add(tileset) viewer.zoomTo(tileset)
附二、只显示 3D Tiles
(1)如果我们希望只显示 3D Tiles,不显示任何地图、影像或地形。可以设置不加载任何底图(Bing 地图),也不加载地形(Terrain)。如果需要,我们还可以设置下背景色(需要关闭天空盒子、大气等)
// 创建 Viewer 实例
this.viewer = new Cesium.Viewer(this.$refs.cesiumContainer, {
imageryProvider: false, // 不加载影像
terrainProvider: new Cesium.EllipsoidTerrainProvider(), // 数学椭球,不会请求任何地形数据
baseLayerPicker: false,
geocoder: false,
timeline: false,
animation: false,
sceneModePicker: false
})
const scene = this.viewer.scene
// 彻底关闭天空盒(有些版本必须用 undefined)
scene.skyBox = undefined
// 彻底关闭大气
scene.skyAtmosphere = undefined
// 关闭雾效(否则仍可能偏蓝)
scene.fog.enabled = false
// 如果 globe 存在,也关掉
scene.globe && (scene.globe.show = false)
// 设置背景色(最后设置)
scene.backgroundColor = Cesium.Color.fromCssColorString('#EDF2FA')
// 加载 Cesium Ion 3D Tiles(全球建筑白模)
const tileset = await Cesium.createOsmBuildingsAsync()
this.viewer.scene.primitives.add(tileset)
(2)只显示全球建筑白模 3D Tiles 数据效果如下:

(3)只显示墨尔本摄影测量 3D Tiles 数据效果如下:

全部评论(0)