☰
在线3DTiles预览工具:多底图切换与坐标微调实战
2026/10/8 9:31:05 网站建设 项目流程

这几年做三维GIS的开发者,应该都有过这种体验:手里拿到一批3DTiles数据——可能是无人机倾斜摄影模型、BIM构件、激光点云——想在浏览器里快速看效果,第一反应往往是本地起个Cesium工程,或者把数据传到Cesium Ion上再说。数据一多、模型一偏移、底图一不对,就得来回折腾。尤其是模型放进场景后发现位置差了几十米甚至几公里,或者朝向不对,这时候最缺的其实不是更复杂的渲染工具,而是一个能在线浏览3DTiles、顺手微调坐标、并把调整结果保存下来的“轻量调试台”。这篇文章就把我一直在用的方案完整拆开讲一遍:免费、在线、支持Cesium默认地图、高德地图、ArcGIS影像、天地图等自定义底图,核心功能是自由切换底图、通过输入坐标和旋转参数精确微调模型位置,最后把整份配置保存成JSON,下次一键加载。适合做三维GIS、智慧城市、BIM运维、倾斜摄影数据处理的同学直接抄作业。

1. 为什么要做一个在线3DTiles预览工具

1.1 先理解3DTiles到底是个什么东西

3DTiles是Cesium社区主导的开放三维瓦片规范,设计目标只有一个:让海量三维数据在浏览器里也能流畅加载。它把倾斜摄影模型、BIM构件、点云、建筑白模等按空间范围切成一层一层的瓦片树,每个瓦片节点独立请求、按视锥裁剪和距离判断动态加载卸载。常见数据格式有b3dm(批量3D模型)、pnts(点云)、i3dm(实例化模型)、cmpt(复合格式)等,b3dm内部往往携带一个或多个GLTF/GLB模型。

打个比方:传统地图瓦片是把地球切成一格一格的正方形图片,3DTiles则是把三维世界切成不同精度等级的“立体瓦片”,根据相机位置和朝向只渲染需要的那部分。所以一份几十GB的倾斜模型,不用全部下载到本地,浏览器也能实时浏览。这也是它这几年成为三维GIS领域事实标准的原因——Cesium、GIS平台、各类三维引擎基本都支持它。

1.2 为什么非要“在线”看,而不是打开桌面软件

很多桌面三维软件都能打开3DTiles,但有几件事在浏览器里做天然更爽。

一是分享和协作的成本几乎为零。你把一个预览页面部署到内网服务器,或者直接用本地服务起一个URL,把链接丢给项目经理、甲方、前端同事,他们不用装任何专业软件,打开浏览器就能看。这种“所见即所得”的沟通方式,比把模型文件打包发过去再教对方安装配置要高效得多。

二是调试坐标偏移时,在线改参数即时看效果,体验完全不一样。倾斜摄影模型经常遇到“放到场景里整体偏了”“楼是斜的”“模型朝向了错误方向”这类问题,我需要在模型和底图之间反复对照,用输入框和滑块微调经纬度、高度、朝向角,边调边看,才能快速找到正确的位置姿态。这在传统桌面软件里往往要改数据源、重新导入导出,循环一次特别慢。

三是和底图叠加验证。三维模型孤零零看着没意义,必须叠到真实地理底图上检查——模型是否压着道路、是否侵入河流、楼顶朝向是否与卫星影像一致。这套在线工具支持Cesium默认底图、高德地图、ArcGIS影像、天地图等多种底图,切换一次只需要几百毫秒,比单独下载影像再叠加方便得多。

1.3 这个工具的核心价值:把“调整”沉淀成配置

做这个工具之前,我处理模型偏移的方式是改代码里的写死的坐标,然后重新编译前端页面。改动一次要几十秒,而且不同项目的配置散落各处,很难复用。

后来我把所有可调参数抽象成一份JSON配置:模型URL、底图类型、经度、纬度、高度、朝向、俯仰、横滚、缩放比例、相机初始视角。在线预览工具提供一个表单,我调整完可以直接保存成JSON文件,下次打开时把JSON拖进页面,一键恢复整个场景。这套思路本质上就是把“调试过程”和“交付结果”统一了——最终交出去的不只是模型,还有一套完整可复现的场景配置。

2. 坐标微调与JSON配置:把“挪位置”这件小事做成标准接口

2.1 微调坐标背后的数学原理

在Cesium中,每个3DTiles对象(Cesium3DTileset)都有一个modelMatrix属性,用来把数据原本的局部坐标系变换到世界坐标系。什么是局部坐标系?很多三维模型在制作软件里是以自己的原点建模的,比如BIM模型可能以建筑中心的某个点为(0,0,0)。放到地球上时,就需要给这个局部原点指定一个经纬度和高度,再决定模型朝向哪个方向。

modelMatrix是一个4x4变换矩阵,平移、旋转、缩放全都可以塞进去。Cesium提供了一个很省事的API:Cesium.Transforms.headingPitchRollToFixedFrame,输入经度、纬度、高度,以及heading、pitch、roll三个欧拉角,直接生成一个把局部坐标系放到地球上指定位置的矩阵。其中:

  • heading(朝向):绕Z轴旋转,0度表示模型正北方向,顺时针为正。
  • pitch(俯仰):绕水平轴旋转,控制模型抬头、低头。
  • roll(横滚):绕前进方向轴旋转,控制模型侧倾。

如果还要整体缩放,再调用Cesium.Matrix4.multiplyByUniformScale,把矩阵乘上一个统一缩放系数。顺序要注意:Cesium的HPR旋转顺序是固定的,新手最容易搞混的是heading的零点方向和正方向约定。我用这个API时习惯先用一个已知坐标的模型做基准测试,确认正北、顺时针方向跟预期一致,避免整个模型调反180度。

2.2 为什么用JSON保存,而不是数据库或二进制

JSON已经成为前后端数据交换的事实标准,用它保存3DTiles场景配置有几个明显优势:

一是可读性极强。它就是纯文本,记事本、VS Code、任何文本编辑器都能打开。网上很多人问“json用什么打开”,其实任何文本编辑器都行,不需要专门的软件。排查问题时直接打开看字段值对不对,非常直观。

二是通用性好。一份JSON配置,既可以被这个在线预览工具读取,也可以被我后续的Cesium项目、后端服务解析,甚至可以用Python脚本批量修改。JSON在ArcGIS、GeoJSON、前端框架里都有完善的生态支持,比如GeoJSON本身就是JSON的扩展,ArcGIS Pro可以直接打开GeoJSON文件,这跟我们的配置JSON是同一个逻辑——数据独立于应用,应用只是它的解释器。

三是天然适配版本管理。配置文件是文本,可以扔进Git仓库,每次调整都有历史记录。模型坐标偏移这种“踩过的坑”,可以直接沉淀在配置的版本历史里,避免反复踩。

2.3 一份实用的配置结构长什么样

我设计的配置结构分三块:基础信息、底图配置、图层列表。图层用数组,因为同一场景可能叠加多个3DTiles模型,比如一个倾斜摄影主体加一栋精细BIM单体。结构如下:

{ "name": "我的3DTiles场景", "version": "1.0", "baseMap": { "type": "tianditu", "layer": "img_w", "token": "你的天地图key" }, "layers": [ { "id": "main", "name": "倾斜摄影", "url": "https://data.example.com/3dtiles/tileset.json", "position": { "longitude": 116.397, "latitude": 39.908, "height": 0.0 }, "rotation": { "heading": 0.0, "pitch": 0.0, "roll": 0.0 }, "scale": 1.0 } ], "camera": { "longitude": 116.397, "latitude": 39.908, "height": 3000.0 } }

实际项目里我还会加一个customProps字段,存放项目编号、负责人、日期等元信息。这个JSON既是工具的唯一输入,也是交付物之一——给同事或甲方时,附上这个文件,他们就能完整复现我调试好的场景。

3. 多底图接入:Cesium、高德、ArcGIS、天地图一把梭

3.1 底图接入的本质:瓦片URL模板

Cesium里的底图本质上是一个ImageryProvider,它知道如何把瓦片坐标拼成一个URL去请求图片。不管是ArcGIS影像、天地图、高德还是Cesium Ion,最终都可以抽象成一行URL模板。Cesium内置了UrlTemplateImageryProvider,我们只需要告诉它URL规则和切片方案。

需要特别注意的是,不同底图用的是不同投影和坐标系。Cesium默认的全球场景基于WGS84椭球体,ArcGIS World Imagery、天地图Web墨卡托瓦片、高德Web墨卡托瓦片都能直接叠进Cesium,但高德瓦片内部使用的是GCJ-02火星坐标系,这是个巨大的坑,下文详说。

3.2 高德地图接入与坐标偏移的坑

高德的瓦片服务地址是公开可用的,常规有两种:

  • 卫星影像:https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}
  • 矢量路网:https://webrd0{1-4}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}

在Cesium里接入时,用UrlTemplateImageryProvider,子域设为['1','2','3','4']。但接入容易,真正麻烦的是坐标系。

高德地图基于GCJ-02火星坐标系,而三维模型一般基于WGS84经纬度生成。GCJ-02相对WGS84有几百米的非线性偏移,具体偏移量随地区不同而变化。所以如果你在高德底图上叠加一个坐标完全正确的WGS84模型,会发现模型整体偏了——这不是模型错了,是底图和模型的坐标系不统一。

我在工具里把“切换高德底图”和“坐标微调”分开做,但逻辑上它们是联动的。切到高德底图后,模型的经纬度输入框通常需要手动微调几百米量级的偏差才能对齐。如果你对位置精度要求高,建议优先用天地图或ArcGIS影像,它们用的是CGCS2000/WGS84体系,和模型坐标基本一致,微调量很小。

还要提一句:高德瓦片服务有防盗链和CORS限制,在局域网或线上环境直接拉可能存在失败问题。个人调试时如果遇到,先在浏览器控制台看具体报错,确认是跨域还是Referer限制,再决定是加代理还是换底图源。

3.3 天地图:Token、投影和图层类型

天地图是国家地理信息公共服务平台,提供了矢量、影像、注记三类在线瓦片,标准WMTS服务,使用前需要到官网免费注册并申请Key。它的瓦片URL典型格式是:

https://t0.tianditu.gov.cn/img_w/wmts ?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0 &LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles &TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=你的token

这里的img_w表示影像图层且使用Web墨卡托投影,vec_w是矢量,cva_w是中文注记。这三个图层通常要叠加使用:影像加上注记才像一张完整的地图。如果你希望使用CGCS2000地理坐标系,可以把TILEMATRIXSET从w改成c,对应图层后缀也要改成img_c、vec_c、cva_c。在Cesium里,用w系列时tilingScheme要设置成new Cesium.WebMercatorTilingScheme(),用c系列时设置成Cesium.GeographicTilingScheme,否则瓦片位置会对不上。

天地图另一个常见问题是Token有域名白名单限制。本地开发用127.0.0.1访问没问题,但上线到正式域名前一定要把域名加到白名单里,否则所有瓦片请求都会失败,控制台全是401或403。

3.4 ArcGIS在线底图和Cesium默认底图

ArcGIS Online提供了几个全球底图服务,其中我最常用的是World Imagery全球影像,URL是:

https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}

这个服务不需要Key,个人和项目演示完全够用,影像分辨率在某些大城市的更新频率也还不错。除了影像,还有World_Street_Map(街道图)和World_Topo_Map(地形图),把URL里的服务名换掉就行。

Cesium默认底图则是Cesium Ion的全球影像,如果你注册了Cesium Ion账号,可以直接用默认底图,也是免费的。在工具里我把Cesium Ion作为“Cesium默认”选项,方便和ArcGIS、高德、天地图做对比。

3.5 底图切换的实现思路

工具里做成一个下拉框,切换时执行两步:先清掉当前所有影像图层,再按配置添加新图层。代码如下:

async function switchBaseMap(type) { // 清空所有现有底图 viewer.imageryLayers.removeAll(); let provider; if (type === 'gaode') { provider = await Cesium.UrlTemplateImageryProvider.fromUrl( 'https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', { subdomains: ['1', '2', '3', '4'], maximumLevel: 18, tilingScheme: new Cesium.WebMercatorTilingScheme() } ); } else if (type === 'tianditu') { provider = await Cesium.UrlTemplateImageryProvider.fromUrl( `https://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${config.baseMap.token}`, { tilingScheme: new Cesium.WebMercatorTilingScheme(), maximumLevel: 18 } ); } else if (type === 'arcgis') { provider = await Cesium.UrlTemplateImageryProvider.fromUrl( 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { maximumLevel: 19 } ); } // 添加为场景底图 viewer.imageryLayers.addImageryProvider(provider); }

注意新版Cesium推荐使用异步的fromUrl,老代码里new Cesium.UrlTemplateImageryProvider()的同步写法在1.107以后会出现警告,新项目建议直接按上面的异步方式写。

4. 实操:从零搭建一个可用的在线3DTiles预览工具

4.1 页面框架与Cesium环境初始化

我用纯前端实现,不引入框架,方便直接部署到任意静态服务器。HTML结构很简单:顶部一个工具条,下面是Cesium容器。工具条里放底图下拉框、模型URL输入框、坐标参数输入区、保存/加载JSON按钮。

<div id="toolbar"> <select id="baseMapSelect"> <option value="cesium">Cesium默认</option> <option value="gaode">高德卫星</option> <option value="tianditu">天地图影像</option> <option value="arcgis">ArcGIS影像</option> </select> <input id="tilesetUrl" placeholder="输入 tileset.json 地址" style="width:300px;" /> <button id="loadTilesetBtn">加载模型</button> <button id="saveJsonBtn">保存JSON</button> <button id="loadJsonBtn">加载JSON</button> <input type="file" id="jsonFileInput" accept=".json" style="display:none;" /> </div> <div id="cesiumContainer"></div>

CesiumJS我直接用CDN引入:

<link href="https://cesium.com/downloads/cesiumjs/releases/1.119/Build/Cesium/Widgets/widgets.css" rel="stylesheet" /> <script src="https://cesium.com/downloads/cesiumjs/releases/1.119/Build/Cesium/Cesium.js"></script>

初始化Viewer时关闭默认底图,后面由我们手动控制:

const viewer = new Cesium.Viewer('cesiumContainer', { baseLayer: false, animation: false, timeline: false, infoBox: false, selectionIndicator: false }); // 设置一个全局初始视角 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(116.397, 39.908, 10000) });

4.2 加载3DTiles并飞入场景

加载3DTiles核心就两步:创建Cesium3DTileset对象、加入scene.primitives。我封装成函数:

let tileset = null; async function loadTileset(url) { if (!url) return; if (tileset) { viewer.scene.primitives.remove(tileset); tileset.destroy(); } try { tileset = await Cesium.Cesium3DTileset.fromUrl(url); viewer.scene.primitives.add(tileset); // 等模型有了包围球后再飞过去 viewer.flyTo(tileset); console.log('模型加载成功'); } catch (err) { console.error('模型加载失败:', err); } }

这里有两个容易踩的坑。第一个是跨域问题:如果tileset.json放在另一个域名,服务端必须返回正确的CORS头,否则模型加载直接失败,控制台会报跨域错误。第二个是加载进度:大模型加载需要时间,我习惯加一个Cesium.Resource的retryCallback给用户提示,避免点了按钮后界面像卡死一样。

4.3 交互式微调坐标的实现

坐标微调区放在工具条里,包含经度、纬度、高度、heading、pitch、roll、缩放比例七个字段。任意字段变化时调用applyTransform():

function applyTransform() { if (!tileset) return; const lon = parseFloat(document.getElementById('inputLon').value); const lat = parseFloat(document.getElementById('inputLat').value); const h = parseFloat(document.getElementById('inputHeight').value); const heading = parseFloat(document.getElementById('inputHeading').value); const pitch = parseFloat(document.getElementById('inputPitch').value); const roll = parseFloat(document.getElementById('inputRoll').value); const scale = parseFloat(document.getElementById('inputScale').value); const position = Cesium.Cartesian3.fromDegrees(lon, lat, h); const hpr = new Cesium.HeadingPitchRoll( Cesium.Math.toRadians(heading), Cesium.Math.toRadians(pitch), Cesium.Math.toRadians(roll) ); let matrix = Cesium.Transforms.headingPitchRollToFixedFrame(position, hpr); matrix = Cesium.Matrix4.multiplyByUniformScale(matrix, scale, matrix); tileset.modelMatrix = matrix; }

实际使用中,纯靠手动输入坐标找位置很慢。我这里加了一个“拾取坐标”按钮:点击地图上的任意位置,把该点经纬度填入输入框,然后微调。这样定位效率高很多。拾取代码如下:

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction((movement) => { const cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid); if (cartesian) { const carto = Cesium.Cartographic.fromCartesian(cartesian); document.getElementById('inputLon').value = Cesium.Math.toDegrees(carto.longitude).toFixed(6); document.getElementById('inputLat').value = Cesium.Math.toDegrees(carto.latitude).toFixed(6); document.getElementById('inputHeight').value = carto.height ? carto.height.toFixed(2) : '0'; applyTransform(); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

调试模型范围时,我还会在地图上画一个矩形参考框,把模型预期范围可视化出来。这对应很多人搜过的“cesium绘制矩形”,其实就是一个实体:

viewer.entities.add({ rectangle: { coordinates: Cesium.Rectangle.fromDegrees(116.38, 39.90, 116.41, 39.92), material: Cesium.Color.YELLOW.withAlpha(0.2), outline: true, outlineColor: Cesium.Color.YELLOW } });

4.4 保存与恢复JSON配置

保存JSON是在线的,不需要后端,直接用浏览器Blob生成文件下载:

function saveConfig() { const config = { name: document.getElementById('sceneName').value || '未命名场景', baseMap: { type: document.getElementById('baseMapSelect').value, token: currentTiandituToken }, layers: [{ id: 'main', name: '主模型', url: document.getElementById('tilesetUrl').value, position: { longitude: parseFloat(document.getElementById('inputLon').value), latitude: parseFloat(document.getElementById('inputLat').value), height: parseFloat(document.getElementById('inputHeight').value) }, rotation: { heading: parseFloat(document.getElementById('inputHeading').value), pitch: parseFloat(document.getElementById('inputPitch').value), roll: parseFloat(document.getElementById('inputRoll').value) }, scale: parseFloat(document.getElementById('inputScale').value) }], camera: { longitude: ..., latitude: ..., height: ... } }; const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${config.name}.json`; a.click(); URL.revokeObjectURL(url); }

恢复配置时,读取文件内容解析成JSON,依次执行切换底图、加载模型、设置变换参数:

document.getElementById('jsonFileInput').addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const text = await file.text(); const config = JSON.parse(text); document.getElementById('baseMapSelect').value = config.baseMap.type; await switchBaseMap(config.baseMap.type); document.getElementById('tilesetUrl').value = config.layers[0].url; await loadTileset(config.layers[0].url); // 填表单并触发变换 document.getElementById('inputLon').value = config.layers[0].position.longitude; // ... 依次赋值 applyTransform(); // 恢复相机位置 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(config.camera.longitude, config.camera.latitude, config.camera.height) }); });

我再加一个localStorage自动保存最近一次配置的机制,页面刷新后自动恢复上次的调试现场,省得频繁下载JSON文件。真正需要交付时再点“保存JSON”导出文件。

5. 常见问题与排查技巧实录

5.1 模型加载不出来、白模、黑屏

这类问题概率最高,排查顺序我总结成一张表:

现象可能性排查方法
控制台跨域报错CORS没有配置数据服务端返回Access-Control-Allow-Origin,或反向代理
模型路径404tileset.json内部相对路径不对检查json里引用的b3dm/glb是否在正确目录
数据没显示但无报错模型矩阵偏移太远,或相机不在包围球附近打开调试,在控制台输出tileset.boundingSphere.center,飞过去看
只有底图没有模型模型缩放为0或高度设置成极大值检查scale字段,确认height在合理范围

尤其是第三类,我遇到过好几次:加载成功后场景里什么都没有,最后发现是模型矩阵把模型挪到了地球另一边。调试时建议先输出tileset.boundingSphere,再把相机飞到该坐标,很快能定位问题。

5.2 模型和底图对不齐:到底是谁偏了

模型和底图位置对不齐,需要分清是哪种偏:

  • 整体平移几米到几十米,且方向一致:多半是GCJ-02和WGS84的坐标系偏移。切到ArcGIS或天地图再对比一次,如果切过去就没问题,那就是坐标系的问题,不是模型问题。
  • 东北方向偏移且随区域变化:可能是模型本身使用了地方坐标系或CGCS2000但无平移参数,需要拿到控制点做七参数转换。
  • 高程整体偏低或偏高:检查高程基准是1985国家高程基准还是椭球高,两者在部分地区差几十米。

我在工具里之所以把底图切换做得很快,就是为了让你能用“对照法”快速判断偏移性质:同一个模型、同一个坐标,换不同底图看偏移方向是否变化。这是排查坐标偏移最快的方法。

5.3 天地图瓦片错位或加载失败

天地图接入后瓦片位置错乱,大概率是tilingScheme选错了。img_w对应Web墨卡托,一定要用Cesium.WebMercatorTilingScheme();如果你用了img_c,则要用Cesium.GeographicTilingScheme()。我见过有人把w和c混着配,结果瓦片一层错位一层正常,看起来像“花屏”。

加载失败则先查Token。天地图Key申请后需要几分钟生效,且绑定域名白名单。本地用localhost或127.0.0.1调试没问题,但换IP或上线前一定要把最终域名加到白名单。控制台如果出现401,可以直接去天地图官网检查Key状态。

5.4 高德瓦片偶尔打不开,或图片空白

高德瓦片服务不是为第三方Cesium直接调用设计的,存在防盗链、Referer校验和访问频控。我自己遇到的情况是:本地打开没问题,部署到服务器上高德瓦片就空白,控制台报CORS或403。解决办法通常是在自己后端加一层瓦片代理,把高德瓦片请求转发回来,或者直接用高德JS API做独立底图再叠加Cesium对象。

这里我再提醒一次:即使高德瓦片成功加载,GCJ-02和WGS84的坐标偏移依旧存在。如果项目对位置精度要求苛刻,建议默认用ArcGIS或天地图。

5.5 shp等二维数据怎么转3DTiles

这个热词出现频率很高,我在做数据预处理时也经常碰到。shp本质是二维矢量数据,没有高度和立体结构,直接转3DTiles出来的只能是贴地平面。常规做法是先用ArcGIS或QGIS根据属性字段做三维化:比如用建筑楼层数乘以层高生成白模体块,或者用DEM高程数据给面要素赋Z值,再导出为带高度的模型格式。

转出来的白模或体块一般是一个glTF/GLB或b3dm集合,之后才能用工具在线预览、调整位置。换句话说,shp转3DTiles不是“一键生成精模”,而是先把二维要素变成三维几何体。这一步做完,再用本文工具验证叠加位置,效率提高很多。

5.6 MVT和3DTiles不是一回事

有同事用Cesium加载MVT矢量瓦片,搞了很久才发现问题。MVT是二维矢量瓦片格式,服务于底图渲染和样式控制,和3DTiles的三维场景管理完全是两条路线。在Cesium里加载MVT需要先把矢量瓦片解析成GeoJSON或使用专门的ImageryProvider处理,不能直接把MVT当3DTiles加载。如果你的数据是二维路网、行政区界线,建议走GeoJSON或ArcGIS动态服务;只有三维模型、点云、倾斜摄影才适合3DTiles。

5.7 JSON配置里存Token是好事还是坏事

我把天地图Token直接写在JSON里,方便调试,但分享文件时要注意Token泄露风险。天地图的Token有配额和域名限制,就算被拿走,别人也只能在你白名单域名下用。稳妥做法是JSON里只存Token字段的占位符,正式部署时由后端注入。这个细节对个人工具无所谓,但做到公司级交付时一定要处理。

6. 一些个人体会:从调试工具到标准配置

我用这套方案做了大半年,最大的体会是:真正消耗时间的不是加载3DTiles本身,而是“模型摆不准”之后一轮轮的来回调试。以前改一个坐标要动代码、重新编译、刷新页面,现在在线工具里输入一个数字、按一下回车,十秒钟就能看到结果。把配置沉淀成JSON之后,项目的交接也轻松了很多——新同事不需要理解我的代码,拿到一个JSON文件就能打开同样的场景。

还有一个隐藏收益:因为配置是JSON,我后来写了一个Python脚本批量读取多个场景的JSON,自动生成一份场景清单文档,包含每个模型的位置、朝向、使用的底图。这份文档直接拿来给甲方确认范围,比截图和口述高效得多。

如果你手里正好有一批3DTiles模型要调试,建议先从一份最小的JSON开始:一个模型、一个底图、一组坐标,跑通整个流程后,再慢慢往里面加图层、切换底图、扩展自定义字段。工具本身不复杂,复杂的是把“在线预览、坐标微调、多底图、JSON持久化”这条链路理顺。一旦理顺,后面接新项目就是换个数据源的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询