ArcGIS JS 基础教程(24):VectorTileLayer 矢量切片图层
- 零、写在前面
- 一、功能介绍
- 二、功能实现
- 2.1 创建并加入 3D 场景
- 2.2 在 3D 中切换样式(loadStyle)
- 2.3 可见性与透明度(3D 通用)
- 三、功能应用
- 四、核心代码
- 五、在线示例
- 六、关键 API 说明
- 七、系列导航
零、写在前面
📌本系列教程完整目录:ArcGIS JS 系列基础教程(100个项目常用热门功能)
💡在线示例:完整可运行的 HTML 示例,无需任何环境配置,可直接在浏览器中打开体验
🗂️专栏导航:收藏 + 关注,专栏文章第一时间送达
❤️一键三连:点赞(给教程充电)+ 评论(提问必回)+ 收藏(下次再看)
一、功能介绍
VectorTileLayer用于加载矢量切片(Vector Tile)服务。与栅格切片(图片)不同,矢量切片在客户端以矢量形式实时渲染样式,因此具有数据量小、缩放无锯齿、支持高 DPI 屏幕、可动态切换样式等优势。
在三维 SceneView中,VectorTileLayer会被自动贴合到地形/地面之上(draped),非常适合作为大比例尺精细底图、暗黑/明亮主题底图,或离线矢量包。
参考:官方 VectorTileLayer API
⚠️三维场景下的限制(务必注意)
- 不能像 2D 那样对单个样式图层做
setPaintProperties/setLayoutProperties等微调,只能整体替换样式。effect(CSS 滤镜特效)在 3D 中不支持;blendMode在 3D 中支持。- 切换样式请使用
loadStyle()方法(整体替换 style JSON)。
二、功能实现
核心 API:VectorTileLayer(@arcgis/core/layers/VectorTileLayer.js)。
2.1 创建并加入 3D 场景
constVectorTileLayer=await$arcgis.import("@arcgis/core/layers/VectorTileLayer.js");// 方式一:通过服务/样式 URLconstvtl=newVectorTileLayer({url:"https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer"});// 方式二:通过 portalItem(本示例采用)constvtl=newVectorTileLayer({portalItem:{id:"7675d44bb1e4428aa2c30a9b68f97822"}});map.add(vtl);// 在 3D 中自动贴合地面2.2 在 3D 中切换样式(loadStyle)
3D 场景无法逐图层改样式,只能整体替换样式文件(style JSON,遵循 MapLibre v8 规范):
// 切换到另一套完整样式vtl.loadStyle("https://www.arcgis.com/sharing/rest/content/items/effe3475f05a4d608e66fd6eeb2113c0/resources/styles/root.json").then(()=>console.log("样式切换完成")).catch(err=>console.error(err));// 还原初始样式(读取只读属性 currentStyleInfo.styleUrl)constoriginal=vtl.currentStyleInfo.styleUrl;vtl.loadStyle(original);2.3 可见性与透明度(3D 通用)
vtl.visible=false;// 隐藏vtl.opacity=0.5;// 半透明(0~1)可见性/透明度/比例尺控制详见第 26 课,本课聚焦「矢量切片 + 三维贴合 + 样式切换」。
三、功能应用
| 应用场景 | 说明 |
|---|---|
| 大比例尺精细底图 | 道路、建筑轮廓等矢量要素在 3D 中清晰呈现,缩放无锯齿 |
| 暗黑/明亮主题切换 | 通过loadStyle()一键切换整套底图样式 |
| 半透明底图叠加 | 设置opacity让矢量底图与影像/地形叠加对比 |
| 离线矢量包 | 矢量切片体积小,适合离线三维场景部署 |
四、核心代码
📦完整代码已保存至
sample/lesson24_vector_tile_layer.html,可直接在浏览器打开。
<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>第24课:VectorTileLayer 矢量切片图层</title><linkrel="stylesheet"href="https://js.arcgis.com/5.0/esri/themes/light/main.css"><scripttype="module"src="https://js.arcgis.com/5.0/"></script><style>*{margin:0;padding:0;box-sizing:border-box;}body{font-family:"Microsoft YaHei",sans-serif;}#mapContainer{width:100vw;height:100vh;}.page-title{position:absolute;top:20px;left:50%;transform:translateX(-50%);background:rgba(255,255,255,0.95);padding:10px 24px;border-radius:6px;font-size:18px;font-weight:bold;z-index:100;box-shadow:0 2px 8pxrgba(0,0,0,0.15);}.control-panel{position:absolute;top:80px;right:20px;background:rgba(255,255,255,0.95);padding:16px;border-radius:8px;box-shadow:0 2px 12pxrgba(0,0,0,0.15);z-index:100;min-width:300px;}.control-panel h3{margin:0 0 8px 0;font-size:14px;color:#333;}.section{margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid #eee;}.section:last-child{border-bottom:none;margin-bottom:0;}.btn-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:6px;}.btn-row button{flex:1;min-width:60px;padding:6px 0;border:1px solid #d9d9d9;border-radius:4px;background:white;cursor:pointer;font-size:12px;}.btn-row button:hover{border-color:#1890ff;color:#1890ff;}.btn-row button.on{background:#1890ff;color:white;border-color:#1890ff;}.info-card{margin-top:10px;padding:10px 12px;background:#f0f5ff;border-radius:6px;border-left:3px solid #1890ff;font-size:12px;line-height:1.6;}.info-card .val{font-weight:bold;color:#1890ff;}.status-text{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,0.7);color:white;padding:8px 20px;border-radius:20px;font-size:13px;z-index:100;pointer-events:none;white-space:nowrap;}</style></head><body><h1class="page-title">第24课:VectorTileLayer 矢量切片图层</h1><divclass="control-panel"><divclass="section"><h3>🗺️ 矢量切片图层(3D 贴合地面)</h3><divclass="btn-row"><buttonid="btnVisible"class="on">👁️ 显示 / 隐藏</button><buttonid="btnOpacity">🌗 透明度</button></div><divclass="btn-row"><buttonid="btnStyleA">🎨 切换暗色样式</button><buttonid="btnStyleReset">↩️ 还原样式</button></div></div><divclass="info-card"><div>图层状态:<spanclass="val"id="layerStatus">加载中...</span></div><div>3D 中 VTL 自动贴合地形</div></div></div><divclass="status-text"id="statusText">VectorTileLayer | 矢量切片 · 3D 贴合地面 · 支持样式切换</div><divid="mapContainer"></div><scripttype="module">constMap=await$arcgis.import("@arcgis/core/Map.js");constSceneView=await$arcgis.import("@arcgis/core/views/SceneView.js");constVectorTileLayer=await$arcgis.import("@arcgis/core/layers/VectorTileLayer.js");constgetTianditu=await$arcgis.import("https://openlayers.vip/examples/resources/tianditu.js");constvecLayers=getTianditu.default({type:"vec_w"});constmap=newMap({basemap:{baseLayers:[vecLayers.base,vecLayers.anno]}});constview=newSceneView({container:"mapContainer",map:map,camera:{position:{longitude:-118.24,latitude:34.05,z:12000},heading:0,tilt:60}});window.view=view;// ===== VectorTileLayer:通过 portalItem 加载矢量切片 =====constvtl=newVectorTileLayer({portalItem:{id:"7675d44bb1e4428aa2c30a9b68f97822"}});map.add(vtl);letoriginalStyle=null;view.when(()=>{vtl.when(()=>{originalStyle=vtl.currentStyleInfo&&vtl.currentStyleInfo.styleUrl;document.getElementById("layerStatus").textContent="已加载";}).catch(err=>{document.getElementById("layerStatus").textContent="加载失败";console.error(err);});});functionsetStatus(msg){document.getElementById("statusText").textContent=msg;}// 显示 / 隐藏document.getElementById("btnVisible").addEventListener("click",function(){vtl.visible=!vtl.visible;this.classList.toggle("on",vtl.visible);setStatus("图层:"+(vtl.visible?"显示":"隐藏"));});// 透明度document.getElementById("btnOpacity").addEventListener("click",()=>{vtl.opacity=vtl.opacity===1?0.5:1;setStatus("透明度:"+vtl.opacity);});// 切换暗色样式(整体替换 style JSON)document.getElementById("btnStyleA").addEventListener("click",()=>{vtl.loadStyle("https://www.arcgis.com/sharing/rest/content/items/effe3475f05a4d608e66fd6eeb2113c0/resources/styles/root.json").then(()=>setStatus("已切换为暗色样式")).catch(err=>setStatus("样式切换失败:"+err.message));});// 还原初始样式document.getElementById("btnStyleReset").addEventListener("click",()=>{if(originalStyle){vtl.loadStyle(originalStyle).then(()=>setStatus("已还原初始样式")).catch(err=>setStatus("样式还原失败:"+err.message));}});</script></body></html>五、在线示例
🔗在线体验:https://southjor.github.io/arcgis-examples/lessons/lesson24.html
操作说明:
- 场景加载后,矢量切片图层自动贴合在三维地形之上。
- 点击「显示 / 隐藏」切换图层可见性。
- 点击「透明度」在
1.0与0.5之间切换,观察半透明叠加效果。- 点击「切换暗色样式」通过
loadStyle()整体替换为暗色样式。- 点击「还原样式」加载
currentStyleInfo.styleUrl回到初始样式。
六、关键 API 说明
| API | 说明 |
|---|---|
new VectorTileLayer({ url | portalItem | style }) | 构造矢量切片图层 |
vtl.loadStyle(styleUrl | styleJson) | 3D 中整体替换样式,返回Promise<void> |
vtl.currentStyleInfo.styleUrl | 只读,当前样式地址(用于还原) |
vtl.visible | 图层显隐(boolean) |
vtl.opacity | 图层透明度(0~1) |
| 3D 限制 | 不支持逐图层改样式(setPaintProperties等仅 2D)、不支持effect |
参考链接:VectorTileLayer API
七、系列导航
⬅️上一篇:ArcGIS JS 基础教程(23):GaussianSplatLayer 高斯泼溅图层
➡️下一篇:ArcGIS JS 基础教程(25):GeoJSONLayer 与 KML 图层
💡小贴士:在三维场景中,
VectorTileLayer最大的价值是轻量、清晰的矢量底图。loadStyle()是 3D 下唯一合法的「换肤」手段——记住它是「整体替换」而非「局部修改」,这与 2D 的setPaintProperties思路完全不同。