使用 deck.gl 与 Esri ArcGIS API for JavaScript 集成:纯 JavaScript 示例实战指南
2026/9/15 12:10:24 网站建设 项目流程

使用 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并挂载到MapView
  • index.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 的桥接模块,提供DeckLayerDeckRendererloadArcGISModules等 API(详见 docs/api-reference/arcgis/overview.md);
  • @deck.gl/core@deck.gl/layers—— deck.gl 核心运行时及内置图层(GeoJsonLayerArcLayer等均来自 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.jsindex.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 将htmlbody#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: 2pointRadiusScale: 2000—— 半径下限(像素)与缩放系数,保证在低缩放级别下点不至于过小;
  • getPointRadius: f => 11 - f.properties.scalerank—— 根据数据的scalerank属性动态决定半径,等级越高(数字越小)半径越大;
  • getFillColor: [200, 0, 80, 180]—— 半透明洋红色填充;
  • pickable: trueautoHighlight: trueonClick—— 开启拾取、悬停高亮与点击弹窗(显示机场名称及缩写)。

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负责显示MapMap通常至少包含一个底图(basemap)。deck.gl 的DeckLayer与普通 ArcGIS 图层完全同构,直接放进map.layers数组即可:

  • container: 'viewDiv'对应 HTML 中的容器元素;
  • basemap: 'dark-gray-vector'选用暗色矢量底图,与弧线、机场点的亮色形成对比;
  • centerzoom将初始视角定位到伦敦(与弧线起点一致),缩放级别 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上还声明了blendModeeffect两个可配置属性,示例中被注释掉的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 强调:DeckLayerDeckRenderer继承自 ArcGIS 核心类,因此只有当 ArcGIS 可用时才存在。ArcGIS API for JavaScript 有两种加载方式,@deck.gl/arcgis的导入方式必须与之匹配:

  1. 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/Mapesri/views/MapViewesri/views/SceneViewesri/views/3d/webgl/RenderNode,并显式指定 ArcGIS CDN 版本https://js.arcgis.com/4.32/,再分别创建 2D 的DeckLayer与 3D 的DeckRenderer

  1. 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)sceneViewviewingMode必须为'local'DeckRenderer会从SceneView的实时相机管理自身的 deck.gl 视图状态,并自动注册为 RenderNode,不要再将其添加到map.layers
  • props直接透传给Deck实例,支持的属性与DeckLayerdeck.*属性集合基本一致(layerseffectsonClickonHover等)。

能力边界与注意事项

overview.md 明确列出了该集成方案的支持范围:

支持的 deck.gl 特性:

  • 图层(Layers)
  • 特效(Effects)
  • 属性过渡(Attribute transitions)
  • 自动高亮(Auto-highlighting)
  • onHoveronClick回调

不支持的特性:

  • 多视图(Multiple views)
  • 控制器(Controller,即由 deck.gl 直接接管交互相机)
  • React 集成(React integration)

抗锯齿注意事项

deck.gl 在此集成中会渲染到一个辅助帧缓冲,再合成进 ArcGIS 场景。该帧缓冲未开启多重采样抗锯齿(MSAA),因此依赖 MSAA 处理边缘的图层——包括PathLayerLineLayerArcLayerPointCloudLayer——会产生明显的锯齿边缘,这与 ArcGIS 上下文本身的抗锯齿设置无关。解决办法是:

  • 在这些图层上显式设置antialiasing: true,让其在着色器中自行计算边缘覆盖率;
  • 对于组合图层(如GeoJsonLayerPolygonLayer),对应属性名为lineAntialiasing

这一点对追求高画质的应用非常关键,本示例中的ArcLayer绘制弧线时同样可以应用该建议。

小结

examples/get-started/pure-js/arcgis示例展示了 deck.gl 与 Esri ArcGIS API for JavaScript 集成的最小完整路径:通过@deck.gl/arcgisDeckLayer,把 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),仅供参考

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

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

立即咨询