使用 deck.gl 与 Esri ArcGIS API for JavaScript 集成:纯 JavaScript 示例实战指南
【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl
本文基于 deck.gl 仓库中的 examples/get-started/pure-js/arcgis 示例,讲解如何在 ArcGIS JavaScript 应用中通过@deck.gl/arcgis模块接入 deck.gl 图层,实现 ArcGIS 底图与 deck.gl 高性能 WebGL 可视化层的同屏渲染。读完本文,你将掌握DeckLayer的接入方式、deck.*属性转发机制、完整示例代码的逐行拆解,以及基于 Vite 的开发与生产构建流程,并了解该集成方案的能力边界与注意事项。
示例概览:ArcGIS 底图上的 deck.gl 图层
examples/get-started/pure-js/arcgis是一个极简的纯 JavaScript(无框架)示例:页面加载 ArcGIS 地图(dark-gray-vector 暗色底图),在其上叠加由DeckLayer承载的两组 deck.gl 图层——用GeoJsonLayer渲染全球机场点、用ArcLayer绘制从伦敦出发的航线弧线。整个工程使用 Vite 负责模块打包与本地服务,支持热更新开发与生产构建。
示例目录仅包含四个文件,结构一目了然:
app.js—— 核心逻辑:创建DeckLayer并挂载到MapViewindex.html—— 页面骨架与 ArcGIS 样式引用package.json—— 依赖声明与 npm 脚本README.md—— 使用说明(即本文所依据的关联文档)
环境准备与依赖安装
首先在示例目录下安装依赖,README 提供了 npm 与 yarn 两种方式:
npm install # 或 yarn从 package.json 可以看到实际安装的依赖:
{ "dependencies": { "@arcgis/core": "^4.28.0", "@deck.gl/arcgis": "^9.0.0", "@deck.gl/core": "^9.0.0", "@deck.gl/layers": "^9.0.0" }, "devDependencies": { "vite": "^7.3.3" } }依赖说明:
@deck.gl/arcgis—— deck.gl 与 ArcGIS 的桥接模块,提供DeckLayer、DeckRenderer、loadArcGISModules等 API(详见 docs/api-reference/arcgis/overview.md);@deck.gl/core与@deck.gl/layers—— deck.gl 核心运行时及内置图层(GeoJsonLayer、ArcLayer等均来自 layers 模块);@arcgis/core—— Esri 官方 ES Modules 形式的 ArcGIS API for JavaScript,本示例采用本地安装的 ES Modules 方式,因此DeckLayer可以直接从@deck.gl/arcgis导入(关于 AMD/CDN 与 ES Modules 两种加载方式的差异,见下文"加载方式的选择");vite—— 开发服务器与构建工具。
运行命令:开发与生产构建
README 给出两条核心命令:
npm start—— 开发模式:启动 Vite 开发服务器并自动打开浏览器,支持热更新(Hot Module Replacement),修改app.js或index.html后页面即时刷新;npm run build—— 生产模式:执行vite build,将源码打包为最终产物并写入磁盘(默认输出到dist/目录)。
此外 package.json 中还提供了一条本地开发脚本:
npm run start-local它通过vite --config ../../../vite.config.local.mjs使用仓库根目录下的 vite.config.local.mjs 配置,便于在 deck.gl 源码仓库内部以本地模块(workspace 中的 modules)替代 npm 发布版本进行联调——如果你正在开发 deck.gl 本身或需要调试最新未发布特性,这条命令会非常有用。
页面骨架:index.html 解析
index.html 是标准的 HTML 入口:
<!doctype html> <html> <head> <meta charset='UTF-8' /> <title>deck.gl w/ Esri ArcGIS API for JavaScript example</title> <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/themes/light/main.css"/> <style> html, body, #viewDiv { padding: 0; margin: 0; width: 100%; height: 100%; } </style> </head> <body> <div id="viewDiv"></div> <script type="module" src='app.js'></script> </body> </html>要点:
- 引入 ArcGIS 官方主题样式
main.css,保证地图控件样式正常; - CSS 将
html、body、#viewDiv全部铺满视口,这是 ArcGIS 地图容器填满整个页面的标准写法; <script type="module">加载app.js,Vite 会将其作为 ES Module 入口进行依赖解析与打包。
核心集成代码逐行拆解
app.js 是整个示例的核心,全部逻辑只有几十行。下面分段说明。
1. 导入依赖与数据源
import {DeckLayer} from '@deck.gl/arcgis'; import {GeoJsonLayer, ArcLayer} from '@deck.gl/layers'; import ArcGISMap from '@arcgis/core/Map'; import MapView from '@arcgis/core/views/MapView'; const AIR_PORTS = 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';DeckLayer是@deck.gl/arcgis提供的 ArcGIS Layer 子类,负责把 deck.gl 图层嵌入 ArcGIS 地图(详见 docs/api-reference/arcgis/deck-layer.md);- 数据源使用 Natural Earth 的全球机场数据(GeoJSON 格式),经 deck.gl 的异步数据加载机制自动拉取。
2. 创建 DeckLayer 并声明 deck.gl 图层
const layer = new DeckLayer({ 'deck.getTooltip': info => info.object && info.object.properties.name, 'deck.layers': [ new GeoJsonLayer({ id: 'airports', data: AIR_PORTS, filled: true, pointRadiusMinPixels: 2, pointRadiusScale: 2000, getPointRadius: f => 11 - f.properties.scalerank, getFillColor: [200, 0, 80, 180], pickable: true, autoHighlight: true, onClick: info => info.object && alert(`${info.object.properties.name} (${info.object.properties.abbrev})`) }), new ArcLayer({ id: 'arcs', data: AIR_PORTS, dataTransform: d => d.features.filter(f => f.properties.scalerank < 4), getSourcePosition: f => [-0.4531566, 51.4709959], // London getTargetPosition: f => f.geometry.coordinates, getSourceColor: [0, 128, 200], getTargetColor: [200, 0, 80], getWidth: 1 }) ] });这里体现了DeckLayer最关键的设计:凡是以deck.前缀开头的属性,都会被转发给内部的一个Deck实例。本示例用到了其中两个:
deck.layers—— 声明要渲染的 deck.gl 图层数组,这是最常用的属性;deck.getTooltip—— 返回悬停提示文本,这里显示机场名称。
GeoJsonLayer的样式与交互配置也很有参考价值:
pointRadiusMinPixels: 2与pointRadiusScale: 2000—— 半径下限(像素)与缩放系数,保证在低缩放级别下点不至于过小;getPointRadius: f => 11 - f.properties.scalerank—— 根据数据的scalerank属性动态决定半径,等级越高(数字越小)半径越大;getFillColor: [200, 0, 80, 180]—— 半透明洋红色填充;pickable: true、autoHighlight: true、onClick—— 开启拾取、悬停高亮与点击弹窗(显示机场名称及缩写)。
ArcLayer则展示了数据预处理与轨迹绘制:
dataTransform: d => d.features.filter(f => f.properties.scalerank < 4)—— 只保留scalerank < 4的机场,减少弧线数量,保证画面清晰;getSourcePosition—— 固定为伦敦坐标[-0.4531566, 51.4709959],所有弧线从伦敦出发;getTargetPosition: f => f.geometry.coordinates—— 目标点为各机场坐标;getSourceColor/getTargetColor—— 起点为蓝色、终点为洋红色,形成渐变视觉效果。
3. 挂载到 ArcGIS MapView
const mapView = new MapView({ container: 'viewDiv', map: new ArcGISMap({ basemap: 'dark-gray-vector', layers: [layer] }), center: [0.119167, 52.205276], zoom: 5 });这段代码遵循 ArcGIS API for JavaScript 的标准组织方式:MapView负责显示Map,Map通常至少包含一个底图(basemap)。deck.gl 的DeckLayer与普通 ArcGIS 图层完全同构,直接放进map.layers数组即可:
container: 'viewDiv'对应 HTML 中的容器元素;basemap: 'dark-gray-vector'选用暗色矢量底图,与弧线、机场点的亮色形成对比;center与zoom将初始视角定位到伦敦(与弧线起点一致),缩放级别 5。
DeckLayer会把内部 deck.gl 视图状态与MapView的相机同步,因此平移、缩放地图时,deck.gl 图层会与 ArcGIS 底图无缝联动。
底层原理:DeckLayer 是如何工作的
深入 modules/arcgis/src 源码可以看到集成的实现方式。核心工厂函数 createDeckLayer 通过 ArcGIS 的Layer.createSubclass创建图层子类,其构造函数内部维护一个deck属性(ArcGISAccessor实例),用于承载全部deck.*转发属性。当MapView需要为图层创建图层视图时,会调用createLayerView(view):
- 若视图类型为
'2d'(即MapView),返回DeckLayerView2D实例,由 deck-layer-view-2d.ts 负责把 deck.gl 渲染进 ArcGIS 的绘制管线; - 若视图为 3D(
SceneView),则明确报错并提示改用DeckRenderer——这印证了"当前DeckLayer仅支持 2D 集成"的限制(见 docs/api-reference/arcgis/deck-layer.md 与 docs/api-reference/arcgis/overview.md)。
DeckLayer上还声明了blendMode与effect两个可配置属性,示例中被注释掉的effect: 'bloom(1.5, 0.5px, 0.1)'展示了一种后处理特效的用法,可在需要时取消注释体验辉光效果。
动态更新 deck 属性
由于deck是一个 ArcGISAccessor,图层创建后仍可随时更新:
// 替换全部图层 layer.deck.layers = [...]; // 批量更新多个属性 layer.deck.set({ layers: [...], pickingRadius: 5, getTooltip: ..., });这在数据源切换、交互参数调整等场景中非常实用。
加载方式的选择:AMD 模块还是 ES Modules
overview.md 强调:DeckLayer和DeckRenderer继承自 ArcGIS 核心类,因此只有当 ArcGIS 可用时才存在。ArcGIS API for JavaScript 有两种加载方式,@deck.gl/arcgis的导入方式必须与之匹配:
- AMD 模块(CDN + esri-loader):若应用通过
esri-loader从 CDN 加载 ArcGIS(例如使用@esri/react-arcgis的场景),则不应直接import {DeckLayer},而应调用loadArcGISModules异步获取集成类:
import {loadArcGISModules} from '@deck.gl/arcgis'; loadArcGISModules(['esri/Map', 'esri/views/MapView'], {version: '4.21'}) .then(({DeckLayer, DeckRenderer, modules}) => { const [ArcGISMap, MapView] = modules; // 之后与示例中用法一致 });loadArcGISModules(modules, loadScriptOptions)接受 esri 模块名数组与 esri-loader 配置,返回的 Promise 解析为{DeckLayer, DeckRenderer, modules}(详见 docs/api-reference/arcgis/load-arcgis-modules.md)。仓库的集成测试应用 test/apps/arcgis/app.js 正是采用这种模式,通过loadArcGISModules同时加载esri/Map、esri/views/MapView、esri/views/SceneView与esri/views/3d/webgl/RenderNode,并显式指定 ArcGIS CDN 版本https://js.arcgis.com/4.32/,再分别创建 2D 的DeckLayer与 3D 的DeckRenderer。
- ES Modules(本地安装 @arcgis/core):本示例即属此类——应用直接
import ArcGISMap from '@arcgis/core/Map',此时DeckLayer也应直接从@deck.gl/arcgis导入。关键原则是:Deck 类的导入方式必须与 ArcGIS 依赖的加载方式保持一致。
另外,若使用独立打包(Standalone Bundle)方式通过<script>标签引入,则只有loadArcGISModules会被导出,DeckLayer/DeckRenderer需在其 Promise 解析后才可用。
3D 集成的实验性方案:DeckRenderer
虽然本示例只演示了 2D 的MapView集成,但@deck.gl/arcgis还提供了针对 3DSceneView的实验性支持——DeckRenderer(详见 docs/api-reference/arcgis/deck-renderer.md):
- 它实现 ArcGIS 的
RenderNode接口,可挂接到 3D 场景的渲染管线; - 目前仅支持
viewingMode: 'local'(局部坐标模式)的SceneView; - 构造函数为
new DeckRenderer(sceneView, props),sceneView的viewingMode必须为'local';DeckRenderer会从SceneView的实时相机管理自身的 deck.gl 视图状态,并自动注册为 RenderNode,不要再将其添加到map.layers; - 其
props直接透传给Deck实例,支持的属性与DeckLayer的deck.*属性集合基本一致(layers、effects、onClick、onHover等)。
能力边界与注意事项
overview.md 明确列出了该集成方案的支持范围:
支持的 deck.gl 特性:
- 图层(Layers)
- 特效(Effects)
- 属性过渡(Attribute transitions)
- 自动高亮(Auto-highlighting)
onHover与onClick回调
不支持的特性:
- 多视图(Multiple views)
- 控制器(Controller,即由 deck.gl 直接接管交互相机)
- React 集成(React integration)
抗锯齿注意事项
deck.gl 在此集成中会渲染到一个辅助帧缓冲,再合成进 ArcGIS 场景。该帧缓冲未开启多重采样抗锯齿(MSAA),因此依赖 MSAA 处理边缘的图层——包括PathLayer、LineLayer、ArcLayer、PointCloudLayer——会产生明显的锯齿边缘,这与 ArcGIS 上下文本身的抗锯齿设置无关。解决办法是:
- 在这些图层上显式设置
antialiasing: true,让其在着色器中自行计算边缘覆盖率; - 对于组合图层(如
GeoJsonLayer、PolygonLayer),对应属性名为lineAntialiasing。
这一点对追求高画质的应用非常关键,本示例中的ArcLayer绘制弧线时同样可以应用该建议。
小结
examples/get-started/pure-js/arcgis示例展示了 deck.gl 与 Esri ArcGIS API for JavaScript 集成的最小完整路径:通过@deck.gl/arcgis的DeckLayer,把 deck.gl 图层作为普通 ArcGIS 图层挂入MapView,配合 Vite 即可获得开发热更新与生产构建能力。其核心机制——deck.*属性转发、createLayerView的 2D/3D 分派、以及 AMD 与 ES Modules 两种加载方式的匹配规则——决定了集成的灵活性也划定了能力边界。无论是希望在 ArcGIS 地图上叠加 GeoJSON 数据、轨迹弧线,还是更进一步探索 3D 的DeckRenderer实验方案,都可以以此为起点快速落地。
如需进一步查阅,可参考仓库内的 @deck.gl/arcgis 模块源码、API 参考文档 以及 集成测试应用。
【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考