deck.gl ScreenGridLayer 独立示例实战指南用 React MapLibre 构建屏幕网格聚合可视化【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.glScreenGridLayer 是 deck.gl 中把海量点数据在屏幕空间聚合为网格直方图并叠加渲染的聚合图层非常适合展示出行热度、人口密度、事件分布等空间聚集场景。本篇文章以仓库中 examples/website/screen-grid 这个最小可运行的独立示例为骨架完整讲解如何从零搭建一个基于 React、MapLibre 与 Vite 的 ScreenGridLayer 应用并深入其官方 API 文档与源码实现帮助你掌握数据格式、核心配置项、GPU/CPU 聚合取舍与拾取交互最终能在自己的项目中直接复制、修改和运行。示例概览一个最小可运行的 ScreenGridLayer 应用examples/website/screen-grid是 deck.gl 官网 ScreenGridLayer 演示的独立精简版。整个目录结构非常简洁只有 5 个文件examples/website/screen-grid/ ├── app.tsx # React 组件定义图层与视图状态 ├── index.html # HTML 入口挂载 React 应用 ├── package.json # 依赖与脚本定义 ├── tsconfig.json # TypeScript 配置 └── README.md # 本示例的使用说明其核心逻辑集中在app.tsx中通过deck.gl/react的DeckGL组件渲染地图与图层用react-map-gl/maplibre提供 MapLibre 底图图层本体则由deck.gl/aggregation-layers导出的ScreenGridLayer承担。示例数据是纽约市 Uber 上下车点pickup locations展示点数据按屏幕网格聚合后的热度分布。快速启动将示例接入你的项目按 README 的说明启动该示例只需三步复制目录将examples/website/screen-grid整个文件夹的内容拷贝到你的项目安装依赖使用npm install或yarn项目使用 Vite 作为构建与开发服务器详见 package.json 中的 scripts启动应用执行npm start等价于vite --open会自动打开浏览器。# install dependencies npm install # or yarn # bundle and serve the app with vite npm startpackage.json中的关键依赖如下版本均来自仓库当前配置依赖版本范围用途deck.gl^9.0.0deck.gl 全家桶含 core / layers / aggregation-layersdeck.gl/react经 deck.gl 导出^9.0.0React 集成组件DeckGLreact/react-dom^18.0.0React 运行时react-map-gl^8.0.0地图容器与底图桥接此处使用其maplibre入口maplibre-gl^5.0.0MapLibre GL 引擎vite^7.3.3开发服务器与打包如果你只想用原生的 deck.gl不使用 React可参考 screen-grid-layer 官方文档 中基于Deck类的写法该文档也提供了 TypeScript 与 React 两种等价写法。数据格式Uber 出行点数据与自定义数据接入示例使用的数据是 deck.gl 官方示例数据集deck.gl-data 仓库中的uber-pickup-locations.json其原始来源为 fivethirtyeight 的 Uber TLC FOIL 响应数据集。在app.tsx中数据通过 URL 直接加载const DATA_URL https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/screen-grid/uber-pickup-locations.json;数据集中的每条记录是一个三元组[longitude, latitude, count]对应类型定义为type DataPoint [longitude: number, latitude: number, count: number];其中第三个分量count作为该位置的**权重weight**参与聚合——示例中通过getWeight: d d[2]取出含义是该网格单元内所有点的权重总和。换成你自己的数据时只需替换data属性。README 指引读者参考 ScreenGridLayer 文档其相对链接在本文中已转换为仓库根路径docs/api-reference/aggregation-layers/screen-grid-layer.md。从app.tsx的 props 签名可以看到data既可以是数据 URL 字符串也可以是内存中的数组data?: string | DataPoint[];也就是说你可以传入任意[lng, lat, weight]形式的点数组或通过getPosition、getWeight两个访问器适配任意字段结构的数据对象例如文档示例中从d.COORDINATES取坐标、从d.SPACES取权重。底图配置CARTO 免费底图与替代方案示例的底图由CARTO 免费底图服务提供配置在app.tsx的MAP_STYLE常量中const MAP_STYLE https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json;这里选用的是 CARTO 的 Dark Matter无标注 样式深色底图能突出彩色聚合网格的对比度。底图通过react-map-gl/maplibre的Map组件渲染并与DeckGL共享同一画布通过reuseMaps复用地图实例避免重复初始化DeckGL device{device} layers{layers} initialViewState{INITIAL_VIEW_STATE} controller{true} Map reuseMaps mapStyle{mapStyle} / /DeckGLREADME 指出如需使用其他底图方案可参考 deck.gl 官方指南 Using other basemap services详见仓库 docs/developer-guide/base-maps 目录下关于地图集成的说明。无论使用 Mapbox、MapLibre 还是 Google Maps核心思路一致用DeckGL的 React 子组件承载对应地图并把mapStyle替换为目标服务的样式 URL。视图状态与图层配置逐项拆解初始视图状态INITIAL_VIEW_STATEconst INITIAL_VIEW_STATE: MapViewState { longitude: -73.75, latitude: 40.73, zoom: 9.6, maxZoom: 16, pitch: 0, bearing: 0 };该状态将视角定位到纽约市上空zoom: 9.6保证网格在默认尺度下具有合理粒度maxZoom: 16限制最大缩放级别。ScreenGridLayer 的核心配置app.tsx中的图层配置如下new ScreenGridLayerDataPoint({ id: grid, data, opacity: 0.8, getPosition: d [d[0], d[1]], getWeight: d d[2], cellSizePixels: cellSize, // 默认 20 colorRange, // 6 级 YlOrRd 风格色带 gpuAggregation, // 默认 true aggregation // 默认 SUM })配合这些配置我们来逐一对照官方文档与源码理解其含义cellSizePixels默认100每个网格单元的宽高像素。源码 screen-grid-layer.ts 中定义其类型为number、最小值为1。示例设为 20表示每 20×20 像素一个聚合单元适合展示高密度城市点数据值越小网格越细、单元数量越多。aggregation默认SUM单元值的聚合操作。官方文档列出的合法值包括SUM权重求和、MEAN均值、MIN最小值、MAX最大值、COUNT落入单元的点数量。getWeight与aggregation共同决定每个单元的值。gpuAggregation默认true是否在浏览器支持时使用 GPU 聚合。源码getAggregatorType()会先检查WebGLAggregator.isSupported(this.context.device)支持则走 GPU 路径否则自动回退 CPU 聚合详见下文性能小节。colorRange色带数组示例自定义了 6 级从浅黄到深红的 YlOrRd 风格色带含 alpha 通道const colorRange: Color[] [ [255, 255, 178, 25], [254, 217, 118, 85], [254, 178, 76, 127], [253, 141, 60, 170], [240, 59, 32, 212], [189, 0, 38, 255] ];默认值为 colorbrewer 的6-class YlOrRd色带。每个颜色为[R, G, B]或[R, G, B, A]四元组通道值范围 0–255省略 Alpha 时按 255 处理。getPosition默认object object.position从每条数据取坐标的访问器。getWeight默认1每条数据的权重。传数字则所有对象共用该权重传函数则逐条求值。示例中d[2]即三元组中的 count 字段。opacity示例设为0.8继承自基础 Layer 属性的整体不透明度。更多渲染选项来自官方文档官方文档还定义了以下可选参数读者可在自定义场景中按需启用cellMarginPixels默认2范围被钳制在[0, 5]单元之间的间隙像素。注意它只影响渲染时的格子外观不改变点的分箱方式源码注释明确说明setting this prop does not affect how points are binned。colorScaleType默认linear数值到颜色的映射方式。linear在colorDomain区间内对colorRange做线性插值quantize则将 domain 均分为与色带数量相等的若干段每段映射一种离散颜色。源码类型定义为linear | quantize。colorDomain默认null自动[min, max]数值区间。未提供时图层在运行期以所有单元的实际最小/最大值作为 domain显式指定则可在不同数据集间保持统一的颜色映射便于横向对比。gpuAggregation、aggregation上文已述cellSizePixels变化会触发重新聚合——源码updateState中监听cellSizePixels、aggregation、dataChanged、viewportChanged等变化并调用aggregator.setProps重算。屏幕空间聚合原理为什么平移缩放会触发重算理解 ScreenGridLayer 的关键在于屏幕空间这三个字。官方文档特别提示聚合发生在屏幕坐标系中因此每当地图缩放或平移图层都必须重新聚合数据。这也是它最适合中小规模数据集的原因——数据量不大时重算开销可控且视觉表现力极强。从源码可以印证这一设计。CPU 聚合路径在createAggregator中把每个点的世界坐标投影到屏幕getValue: ({positions}: {positions: number[]}, index: number, opts: BinOptions) { const viewport this.context.viewport; const p viewport.project(positions); const cellSizePixels: number opts.cellSizePixels; if (p[0] 0 || p[0] viewport.width || p[1] 0 || p[1] viewport.height) { // Not on screen return null; } return [Math.floor(p[0] / cellSizePixels), Math.floor(p[1] / cellSizePixels)]; }可以看到投影后落在视口之外的[lng, lat]点会被丢弃视口内的点按floor(屏幕坐标 / cellSizePixels)归入对应网格单元——这就是分箱binning过程。GPU 路径则把同一逻辑写成 GLSL 顶点着色器getBin中通过project_position_to_clipspace投影并计算gridCoords由 WebGL 并行完成。updateState中还有一条关键逻辑当viewportChanged为真时调用aggregator.setNeedsUpdate()强制重算与文档的说明完全吻合。另外注意屏幕网格聚合是2 维分箱dimensions: 2单元由col列、row行唯一标识在 GPU 路径下分箱范围按当前视口尺寸动态计算binIdRange见 screen-grid-layer.ts。GPU 与 CPU 聚合的取舍gpuAggregation的默认值为true但并非所有场景都应开启。官方 Aggregation Layers 总览 的 CPU vs GPU Aggregation 一节给出了权威指导兼容性GPU 聚合所需的浏览器能力已被现代浏览器广泛支持覆盖 95% 的全球市场但个别设备/芯片的驱动差异可能影响结果。数据规模CPU 聚合耗时与数据量大致线性相关GPU 聚合有初始化着色器与上传缓冲的前期开销但处理更多数据的边际成本很小。数据量大于约 10 万时 GPU 显著更快小数据集下 GPU 反而可能更慢。数据分布CPU 聚合内存与至少含一个点的单元数成正比GPU 聚合内存与所有可能单元数含空单元成正比。点越密集集中GPU 优势越明显点越稀疏分散越不适合 GPU。扩展ExtensionsDataFilterExtension、MaskExtension等基于 GPU 的扩展仅支持 GPU 聚合。精度GPU 着色器仅支持 32 位浮点虽做了缓解措施但结果可能与 CPU 聚合存在微小差异仓库测试会校验二者的一致性在可接受范围内。访问单元内点GPU 聚合不暴露单元内的具体数据点若你需要点选单元后列出其中的位置列表这类功能只能改用 CPU 聚合或手动过滤数据。这一点直接对应拾取信息中pointIndices/points字段仅 CPU 聚合可用的限制。官方文档给出的参考性能数据2016 款 15 英寸 MacBook Pro 上的随机数据25K 点时 GPU 反而慢约 33%100K 点时 GPU 快约 267%1M 点时 GPU 快约 1144%。拾取交互hover/click 返回的单元对象官方文档规定ScreenGridLayer 的 hover/click 事件中PickingInfo.object代表一个聚合后的网格单元包含以下字段字段类型说明colnumber单元列索引从视口左侧 0 开始rownumber单元行索引从视口顶部 0 开始valuenumber聚合值由getWeight与aggregation共同决定countnumber落在该单元内的数据点数量pointIndicesnumber[]单元内数据对象的索引仅 CPU 聚合可用pointsobject[]单元内的数据对象仅 CPU 聚合且 data 为数组时可用这一行为在源码getPickingInfo中有明确实现screen-grid-layer.ts命中单元后组装{col, row, value, count}并在bin.pointIndices存在时补上pointIndices与points。在示例中给DeckGL加上getTooltip即可展示提示框例如getTooltip: ({object}) object Count: ${object.value}文档中的 TypeScript 示例使用了ScreenGridLayerPickingInfoBikeRack类型从deck.gl/aggregation-layers导入源码定义见 screen-grid-layer.ts可让拾取对象获得完整的类型提示。安装方式补充与测试佐证除了通过deck.gl全家桶引入官方文档还提供了按模块安装的方式npm install deck.gl # 或 npm install deck.gl/core deck.gl/layers deck.gl/aggregation-layers对应导入语句为import {ScreenGridLayer} from deck.gl/aggregation-layers类型ScreenGridLayerProps、ScreenGridLayerPickingInfo亦从此模块导出也支持通过 unpkg 的预打包脚本dist.min.js在纯 HTML 中直接使用全局deck.ScreenGridLayer。仓库对 ScreenGridLayer 有完善的自动化测试可作进一步参考单元测试位于 test/modules/aggregation-layers/screen-grid-layer.spec.ts使用deck.gl/test-utils的generateLayerTests与testLayer覆盖各 prop 组合网格单元渲染测试见screengrid-cell-layer.spec.ts聚合器实现位于 modules/aggregation-layers/src/common/aggregatorCPUAggregator与WebGLAggregator。想深入了解图层渲染层可阅读 modules/aggregation-layers/src/screen-grid-layer 目录下的screen-grid-cell-layer.ts与 GLSL/WGSL 着色器文件。总结examples/website/screen-grid是一个麻雀虽小五脏俱全的 deck.gl 实战模板它演示了从依赖安装、数据接入、底图配置到图层参数调优的完整链路并天然覆盖了 ScreenGridLayer 最核心的屏幕空间聚合特性与 GPU/CPU 双路径实现。掌握了这份示例之后你可以基于 ScreenGridLayer 官方文档 继续探索cellMarginPixels、colorScaleType、colorDomain等进阶参数或参考 Aggregation Layers 总览 了解 GridLayer、HexagonLayer、HeatmapLayer、ContourLayer 等其他聚合图层的异同把屏幕网格聚合能力平滑扩展到自己的业务数据之上。【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考