在Autodesk Forge Viewer中添加Mapbox切片图层的问题
问题描述
正在学习基于Geodjango、Mapbox和Openlayers的GIS开发,已在Autodesk Forge Viewer中创建应用,完成Bucket创建并添加了3D模型。但目前无法在3D模型下方添加Mapbox切片图层,尝试创建Mapbox样式并在JavaScript代码中关联API后,地图仍未显示。以下是使用的JavaScript代码:
class MyMapboxForgeExtension extends Autodesk.Viewing.Extension { constructor(viewer, options) { super(viewer, options); } quad(x,y) { const mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 256, 256 ), new THREE.MeshNormalMaterial({ color:0xa0a0a0, depthWrite:false, map: (THREE.ImageUtils.loadTexture(`https://api.mapbox.com/styles/v1/snex-tech/cl9ie4t7h00kv15qrta7poy29.html?title=view&access_token=pk.eyJ1Ijoic25leC10ZWNoIiwiYSI6ImNsOWZqbnV6bzAyMDQzd29hNXk2cWgwOHAifQ.-qMPioM3OUUHLWgClmsthw&zoomwheel=true&fresh=true#2/37.75/-92.25`)) }) ); mesh.position.set (x*256,y*256, 1); return mesh; } load() { this.viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, ()=>{ if (!this.viewer.overlays.hasScene('map')) { this.viewer.overlays.addScene('map'); } const tiles = new THREE.Object3D(); tiles.position.set(-1140,-800, -10); tiles.scale.set(2,2,1); const tilex = [-1,0,1,2,3]; const tiley = [0,1,2]; tilex.map( x => { tiley.map( y => { tiles.add(this.quad(x,y)); })}); window.tiles=tiles; this.viewer.overlays.addMesh(tiles, 'map'); }); return true; } unload() { return true; } } Autodesk.Viewing.theExtensionManager.registerExtension('MyMapboxForgeExtension', MyMapboxForgeExtension);
问题排查与修复方案
- Mapbox纹理URL错误:当前使用的是Mapbox样式的预览页面URL,而非瓦片图的API服务地址。必须替换为Mapbox标准瓦片服务URL,格式为
https://api.mapbox.com/styles/v1/{username}/{style_id}/tiles/{zoom}/{x}/{y}?access_token={access_token} - 材质选型错误:
MeshNormalMaterial用于显示法向量颜色,不适合加载纹理贴图。应改用MeshBasicMaterial或MeshLambertMaterial,同时调整深度属性确保地图图层显示在3D模型下方 - 废弃API使用:
THREE.ImageUtils.loadTexture已被Three.js废弃,需替换为THREE.TextureLoader - 层级位置问题:需确保地图瓦片的z轴位置数值小于3D模型的最低z值,保证图层层级正确
修正后的代码
class MyMapboxForgeExtension extends Autodesk.Viewing.Extension { constructor(viewer, options) { super(viewer, options); // 配置Mapbox参数 this.mapboxUsername = 'snex-tech'; this.mapboxStyleId = 'cl9ie4t7h00kv15qrta7poy29'; this.mapboxToken = 'pk.eyJ1Ijoic25leC10ZWNoIiwiYSI6ImNsOWZqbnV6bzAyMDQzd29hNXk2cWgwOHAifQ.-qMPioM3OUUHLWgClmsthw'; } // 生成Mapbox瓦片URL getMapTileUrl(x, y, zoom = 2) { return `https://api.mapbox.com/styles/v1/${this.mapboxUsername}/${this.mapboxStyleId}/tiles/256/${zoom}/${x}/${y}?access_token=${this.mapboxToken}`; } quad(x, y, zoom = 2) { const textureLoader = new THREE.TextureLoader(); const texture = textureLoader.load(this.getMapTileUrl(x, y, zoom)); const mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry(256, 256), new THREE.MeshBasicMaterial({ map: texture, depthWrite: false, // 禁止写入深度缓冲区,避免遮挡模型 depthTest: true, // 启用深度测试,确保显示在模型下方 transparent: false }) ); mesh.position.set(x * 256, y * 256, -10); // z值设置为低于模型的层级 return mesh; } load() { this.viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, () => { if (!this.viewer.overlays.hasScene('map')) { this.viewer.overlays.addScene('map'); } const tiles = new THREE.Object3D(); tiles.position.set(-1140, -800, 0); tiles.scale.set(2, 2, 1); const tilex = [-1, 0, 1, 2, 3]; const tiley = [0, 1, 2]; tilex.forEach(x => { tiley.forEach(y => { tiles.add(this.quad(x, y)); }); }); this.viewer.overlays.addMesh(tiles, 'map'); }); return true; } unload() { // 清理地图场景资源 if (this.viewer.overlays.hasScene('map')) { this.viewer.overlays.removeScene('map'); } return true; } } Autodesk.Viewing.theExtensionManager.registerExtension('MyMapboxForgeExtension', MyMapboxForgeExtension);
额外说明
- 可根据需求调整瓦片的
zoom级别,匹配3D模型的地理范围 - 如果需要更精准的地理对齐,需将Forge模型的坐标与Mapbox的WGS84坐标系进行转换
- 若仍无法显示,可在浏览器控制台查看是否有跨域或Token权限错误
内容的提问来源于stack exchange,提问作者THADEUS ODHIAMBO LWANDE
相关产品推荐
相关产品推荐

