maptalks.three 矢量瓦片教程:ThreeVectorTileLayer 三维瓦片渲染完全指南
【免费下载链接】maptalks.threeA maptalks layer to render with three.js.项目地址: https://gitcode.com/gh_mirrors/ma/maptalks.three
maptalks.three 是一款基于 three.js 渲染的 maptalks 图层插件,其内置的ThreeVectorTileLayer 矢量瓦片图层可按瓦片加载 GeoJSON/MVT 矢量数据,自动生成立体建筑、三维道路线与点要素,是构建轻量级三维城市可视化的利器。本文面向新手,带你从零完成三维瓦片渲染上手。
🗺️ 什么是矢量瓦片?ThreeVectorTileLayer 解决什么问题?
传统三维 GIS 应用要把整份 GeoJSON 一次性灌入渲染引擎,数据量大时首屏卡顿、内存暴涨。矢量瓦片(Vector Tile)把地理数据按z/x/y切分成小块,视野变到哪、加载到哪,天然适合海量数据的渐进式渲染。
ThreeVectorTileLayer 继承自 maptalks 的 TileLayer,它接管瓦片调度,把每个瓦片的 GeoJSON 数据自动转换成 three.js 图形对象并挂到 ThreeLayer 的 WebGL 场景中:
| 要素类型 | 自动转换成的三维对象 | 要求的材质类型 |
|---|---|---|
| 多边形(建筑、地块) | ExtrudePolygons 立体挤出多边形 | 任意 THREE.Material(推荐 MeshPhongMaterial) |
| 线(道路、水系) | Lines 三维线条 | LineBasicMaterial / LineDashedMaterial |
| 点(兴趣点) | Points 点云 | PointsMaterial |
它的核心实现位于 ThreeVectorTileLayer.ts 与 BaseVectorTileLayer.ts。
📦 快速安装:maptalks.three 依赖与加载顺序
方式一:npm 安装
npm install maptalks.three方式二:浏览器脚本引入(注意加载顺序)
maptalks.three是 maptalks 的插件,必须先加载 three.js 和 maptalks.js,最后再加载 maptalks.three:
<script src="three.min.js"></script> <script src="maptalks.min.js"></script> <script src="maptalks.three.min.js"></script>💡 版本提示:three.js >= 128 时官方默认提供 ES6 的 UMD 包;若运行环境不支持 ES6,请使用配套的 ES5 版本(对应 three.js <= 127)。
🚀 三步上手:toThreeVectorTileLayer 创建三维瓦片图层
创建流程非常简洁——先建 ThreeLayer,再调用工厂方法,最后map.addLayer:
// 1. 创建 ThreeLayer(三维渲染容器) const threeLayer = new maptalks.ThreeLayer('t', { forceRenderOnMoving: true, forceRenderOnRotating: true }); // 2. 创建矢量瓦片图层(url 支持 {z}/{x}/{y} 占位符) const vectorTileLayer = threeLayer.toThreeVectorTileLayer( 'http://your-server/tile/{z}/{x}/{y}', // 瓦片数据地址模板 { minZoom: 10, maxZoom: 16, interactive: false, // 是否开启拾取交互 worker: false // 是否用 Worker 异步构建网格 }, getMaterial // 材质回调函数(见下文) ); // 3. 加入地图 threeLayer.prepareToDraw = function (gl, scene, camera) { const light = new THREE.DirectionalLight(0xffffff); light.position.set(0, -10, -10).normalize(); scene.add(light); map.addLayer(vectorTileLayer); }; threeLayer.addTo(map);toThreeVectorTileLayer的完整签名见 index.ts,返回一个标准的ThreeVectorTileLayer实例,支持show() / hide() / remove()等 TileLayer 通用方法。
🎨 核心灵魂:getMaterial 材质回调怎么写?
getMaterial(layerName, data, index, geojson)会在每个瓦片数据到达时被调用,按图层名(layerName)返回材质,决定这一组要素长什么样:
const roadMaterial = new THREE.LineBasicMaterial({ color: 'rgb(43,69,107)' }); const buildMaterial = new THREE.MeshPhongMaterial({ color: '#fff', transparent: true }); function getMaterial(layerName, data, key, geojson) { switch (layerName) { case 'roads': return roadMaterial; case 'buildings': return buildMaterial; default: return null; // 返回 null = 不渲染该图层 } }⚠️新手最常见的"不渲染"坑:材质类型必须与要素匹配——道路线条必须是LineBasicMaterial或LineDashedMaterial,点必须是PointsMaterial,否则该要素会被直接跳过。
瓦片数据格式约定
每个瓦片 URL 应返回一个JSON 对象,键是图层名,值是 FeatureCollection(或 Feature 数组):
{ "buildings": { "type": "FeatureCollection", "features": [ ... ] }, "roads": { "type": "FeatureCollection", "features": [ ... ] } }💡 立体建筑的高度请写进每个要素的
properties.height中,图层会据此挤出不同高度的三维楼体。
⚙️ 数据加载机制:队列调度 + 按需缓存
ThreeVectorTileLayer 内部有一套精巧的调度机制,理解它能帮你优化性能:
- 瓦片数据队列:所有瓦片请求进入 TileDataQueue.ts 队列,逐帧消费、分批构建网格,避免同一时刻大量数据涌入导致掉帧;
- 视野同步:监听
layerload事件,视野内新瓦片自动加入、滑出视野的瓦片自动移除; - 缓存回收:缓存超过
tileCache.max时批量dispose不再使用的 geometry,释放显存; - Worker 异步构建:设置
worker: true后,网格构建移入 Web Worker(见 worker.ts),大数据量下主线程不再卡顿。
还可以覆盖getTileData(q)自定义数据获取方式(例如加超时、做模拟延时平滑掉帧),demo 中有现成写法:
vectorTileLayer.getTileData = function (q) { const { key, url, callback, img } = q; // 用自己的 fetch/axios 拉取瓦片,成功后 callback(key, geojson, img) };🖱️ 交互增强:拾取高亮与事件回调
设置interactive: true后,通过重写onSelectMesh就能拿到点击/悬停命中的三维对象,做高亮或信息窗:
vectorTileLayer.onSelectMesh = function (type, e) { if (type === 'click' && e.select) { const baseObject = e.select.baseObject; baseObject.setSymbol(highlightMaterial); // 换高亮材质 } };配合vectorTileLayer.getBaseObjects()还能拿到当前所有三维对象,批量设置setAltitude()抬升整体高度、或用animateShow()播放入场动画。
❓ 常见问题与性能调优清单
- 建筑没显示?检查
getMaterial返回的材质类型是否匹配要素(见上文对照表); - 移动地图掉帧?开启
worker: true,或覆盖getTileData加随机延时错峰处理; - 想动态显隐图层?直接调用
vectorTileLayer.show() / hide(),内部会自动同步所有 BaseObject 的可见性; - 楼层纹理想要更真实?给建筑材质叠加贴图,例如项目里的夜景建筑纹理(见 demo-bak/vectortilelayer.html 中的 dat.GUI 调色面板):
📚 延伸阅读:源码与示例地图
| 资源 | 路径 |
|---|---|
| 矢量瓦片图层主实现 | src/ThreeVectorTileLayer.ts |
| 瓦片基类(加载/缓存机制) | src/BaseVectorTileLayer.ts |
| 瓦片数据队列 | src/queue/TileDataQueue.ts |
| ThreeLayer 完整 API 文档 | docs/api/threelayer.md |
| 选项类型定义 | docs/api/types.md |
| GeoJSON 瓦片演示 | demo-bak/vectortilelayer.html |
| 本地 GeoJSON 转瓦片演示 | demo-bak/vectortilelayer-geojson-vt.html |
| MVT 瓦片演示 | demo-bak/vectortilelayer-mvt.html |
掌握以上要点后,你就可以把任意 GeoJSON/MVT 瓦片服务接入 maptalks.three,几分钟搭出一个可交互、可拾取、按瓦片渐进加载的三维地图应用。🎉
【免费下载链接】maptalks.threeA maptalks layer to render with three.js.项目地址: https://gitcode.com/gh_mirrors/ma/maptalks.three
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考