ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

deck.gl ContourLayer 独立示例实战:从 COVID-19 数据到等值线/等值带可视化

deck.gl ContourLayer 独立示例实战:从 COVID-19 数据到等值线/等值带可视化 deck.gl ContourLayer 独立示例实战从 COVID-19 数据到等值线/等值带可视化【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl本篇文章围绕 deck.gl 仓库中的 ContourLayer 最小独立示例examples/website/contour展开完整讲解如何将示例复制到自己的项目、安装依赖并启动 Vite 开发服务器同时结合示例代码与 ContourLayer API 文档、聚合层模块源码深入剖析等值线Isoline与等值带Isoband的生成原理、全部核心属性cellSize、contours、aggregation、zOffset等及底层实现。读完本文你将能够独立运行该示例、理解 Marching Squares 算法如何被应用到聚合网格上并把它改造成自己的等值线可视化应用。示例概览一个最小的 ContourLayer 应用examples/website/contour是 deck.gl 官方 ContourLayer 示例的最小独立版本目录结构非常精简仅包含 5 个文件app.tsx—— 应用主逻辑包含数据加载、ContourLayer 配置、底图与 Tooltipindex.html—— 入口 HTML通过script typemodule引入app.tsxpackage.json—— 依赖与脚本声明Vite 构建tsconfig.json—— TypeScript 配置README.md—— 运行说明即本文展开讲解的原始文档从 package.json 可以看到示例基于 React 18 Vite 构建核心依赖为deck.gl^9.0.0、maplibre-gl^5.0.0与react-map-gl^8.0.0其中deck.gl/aggregation-layers提供了本次主角ContourLayer。index.html加载了 maplibre-gl 的样式文件并将挂载点指向div idapp随后调用app.tsx导出的renderToDOM完成渲染。该示例使用美国各县每周新增 COVID-19 病例数据按每 10 万居民归一化通过等值带Isoband与等值线Isoline两种形式直观展示疫情的空间分布态势。快速开始安装依赖并启动示例 README 给出的运行流程非常直接将整个文件夹内容复制到你的项目然后执行安装与启动命令# 安装依赖 npm install # 或者使用 yarn yarn # 使用 Vite 打包并启动开发服务器 npm start对应 package.json 中的脚本定义npm start等价于vite --open启动开发服务器并自动打开浏览器npm run start-local使用仓库根目录下的vite.config.local.mjs配置用于在 deck.gl monorepo 内以本地源码方式联调npm run build执行vite build产出生产构建。如果你的项目尚未初始化也可以参考 安装指南 单独安装所需模块npm install deck.gl # 或按需安装 npm install deck.gl/core deck.gl/layers deck.gl/aggregation-layers随后在代码中引入import {ContourLayer} from deck.gl/aggregation-layers; import type {ContourLayerProps, ContourLayerPickingInfo} from deck.gl/aggregation-layers; new ContourLayerDataT(...props: ContourLayerPropsDataT[]);示例数据格式COVID-19 病例数据示例使用的数据文件是covid-by-county.json由app.tsx中的DATA_URL常量指向 deck.gl 官方示例数据仓库。每个数据对象的结构如下对应app.tsx中的CaseReport类型type CaseReport { state: string; // 州名 county: string; // 县名 longitude: number; // 经度 latitude: number; // 纬度 population: number; // 人口数 casesByWeek: {[week: number]: number}; // 按周索引的病例数week 为周序号 };在app.tsx中getPosition直接返回[d.longitude, d.latitude]而getWeight将某一周week参数的病例数除以人口再乘以1e5得到每 10 万居民的新增病例数作为权重值getPosition: d [d.longitude, d.latitude], getWeight: d ((d.casesByWeek[week] || 0) / d.population) * 1e5,更换自己的数据时只需保证数据对象能通过getPosition与getWeight两个 accessor 提供坐标和权重即可格式并不强制。更完整的字段说明可查看 ContourLayer 文档。底图配置CARTO 免费底图服务示例的底图由 CARTO 免费底图服务提供默认样式为https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json深色底图与彩色等值带形成高对比。在app.tsx中通过react-map-gl/maplibre的Map组件嵌入DeckGL initialViewState{INITIAL_VIEW_STATE} controller{true} layers{layers} getTooltip{getTooltip} style{{mixBlendMode: lighten}} Map reuseMaps mapStyle{mapStyle} / /DeckGLstyle{{mixBlendMode: lighten}}使 deck.gl 渲染的等值带与底图以变亮模式混合等值带颜色只会使底图变亮而不会压暗视觉上更干净。示例的INITIAL_VIEW_STATE定位在全美范围经度 -100、纬度 40、zoom 3、maxZoom 10。如需替换为其他底图方案可将mapStyle换成任意符合 MapLibre GL Style 规范的样式地址。核心概念等值线Isoline与等值带IsobandContourLayer的作用是将离散点数据聚合成连续场再绘制出等值线或等值带。按官方文档的定义Isoline等值线一组把高于某阈值与低于某阈值区域分隔开的线段集合。生成它只需要一个阈值数值Isoband等值带填充某一阈值范围内区域的多边形集合。生成它需要一个包含两个数值的数组。数据的处理流程为先用指定的cellSize格网单元尺寸对数据进行聚合得到一个标量场每个网格单元一个值再对该标量场运行Marching Squares行进方形算法生成构成等值线或等值带的顶点序列。文档与源码中统一将二者合称为contour。在 contour-layer.ts 中这一流程的调用链清晰可见聚合结果通过getAggregatorValueReader封装为(x, y) value的值读取函数随后generateContours在binIdRange网格单元范围内逐格遍历对每个格子调用marching-squares.ts中的getCode、getLines、getPolygons生成线段与多边形详见下文源码分析。核心属性详解以下属性均可直接从 contour-layer.ts 的defaultProps与 官方文档 中得到印证。聚合选项cellSizenumber可选默认1000每个网格单元的边长单位为米。示例中设为6000060 公里因为 COVID-19 数据覆盖全美需要较大的单元才能形成平滑的场。文档中的自行车停放点示例则使用200米。属性声明中还包含min: 1的下限约束。gpuAggregationboolean可选默认true当为true且浏览器支持时聚合在 GPU 上执行否则回退到 CPU 聚合。在 contour-layer.ts 中通过WebGLAggregator.isSupported判断 GPU 可用性不可用时自动使用CPUAggregator。两者各有取舍详见下文CPU vs GPU 聚合章节。aggregationstring可选默认SUM定义所有落入同一网格单元的数据点权重如何合并为该单元的值合法取值包括SUM落入单元的所有点权重之和MEAN落入单元的权重平均值MIN最小值MAX最大值COUNT落入单元的点数量示例使用MAX即每个网格单元取该区域所有县中每 10 万居民新增病例数的最大值从而避免单元内多县人口差异被求和掩盖。源码中该值会作为operations传入 aggregatorcontour-layer.ts。渲染选项contoursobject[]可选默认[{threshold: 1}]等值线/等值带配置数组。注意与普通 prop 一样contours采用浅比较判断是否变化因此应将其作为数组对象整体传入仅在需要变更时替换。每个配置项包含以下键键类型说明thresholdnumber或number[2]等值线时为一个数值等值带时为[min, max)区间即渲染 threshold[0]且 threshold[1]的区域下限包含、上限不包含colorColor可选RGBA 颜色数组默认[255, 255, 255, 255]若只给 RGB 三分量Alpha 自动取 255strokeWidthnumber可选仅对等值线生效线宽像素默认1zIndexnumber可选等值线/带的 z 层级值越大的渲染在越上层用于重叠 contour 的精确排布可避免 z-fighting缺省时自动分配0到ncontour 数量的唯一值示例中定义了两套 contour 配置分别用于两种可视化模式// 等值带BANDS按病例密度从低到高、颜色从浅黄到深红渐变 export const BANDS [ {threshold: [0.1, 1], color: [255, 255, 178]}, {threshold: [1, 10], color: [254, 204, 92]}, {threshold: [10, 100], color: [253, 141, 60]}, {threshold: [100, 500], color: [240, 59, 32]}, {threshold: [500, 2000], color: [189, 0, 38]}, {threshold: [2000, 10000], color: [159, 0, 80]} ]; // 等值线LINES六个阈值统一的线宽 export const LINES [ {threshold: 1, color: [255, 255, 178], strokeWidth: 2}, {threshold: 10, color: [254, 204, 92], strokeWidth: 2}, // ... 依次为 100、500、2000、10000 ];这也是文档中官方示例旧金山自行车停放点数据的风格多个等值线阈值配不同颜色与线宽、不同zIndex保证压盖顺序contours: [ {threshold: 1, color: [255, 0, 0], strokeWidth: 2, zIndex: 1}, {threshold: [3, 10], color: [55, 0, 55], zIndex: 0}, {threshold: 5, color: [0, 255, 0], strokeWidth: 6, zIndex: 2}, {threshold: 15, color: [0, 0, 255], strokeWidth: 4, zIndex: 3} ]zOffsetnumber可选默认0.005为等值线/等值带每个顶点附加的极小 z 偏移用于控制重叠 contour 的纵向排布。例如当等值线压在等值带上时需要给等值线更大的偏移使其显示在上层避免 z-fighting。数据访问器getPositionAccessor可选默认object object.position用于从每个数据对象中取位置坐标。getWeightAccessor可选默认1每个对象的权重。可以是常数所有对象权重相同也可以是函数对每个对象调用取权重。该值与aggregation共同决定网格单元的数值。示例代码逐段解析将 app.tsx 与 README 结合可以看到一个完整示例包含的四个关键部分1. 数据与视图状态。DATA_URL指向 COVID-19 数据INITIAL_VIEW_STATE定义全美视角。2. Layer 配置。核心是contours、cellSize、aggregation与两个 accessor 的组合new ContourLayerCaseReport({ data, id: contour-layer, getPosition: d [d.longitude, d.latitude], getWeight: d ((d.casesByWeek[week] || 0) / d.population) * 1e5, updateTriggers: {getWeight: week}, // week 变化时重新聚合 pickable: true, aggregation: MAX, contours, cellSize })updateTriggers: {getWeight: week}是关键优化切换周次时仅更新权重访问器避免不必要的全量更新。3. Tooltip 定制。通过info.object.contour.threshold判断命中的等值带区间将阈值映射为人类可读文案const {threshold} info.object.contour; if (threshold[1] 1) str 1 new case; else if (threshold[0] 2000) str 2,000 new cases; else str ${threshold[0]}-${threshold[1]} new cases;并利用week反推周日期以 2020-01-20 为第 0 周const date new Date(Date.UTC(2020, 0, 20) week * MS_PER_WEEK);4. 地图容器。DeckGL内嵌 MapLibreMap组件controller{true}启用交互平移、缩放style{{mixBlendMode: lighten}}实现底图与等值带的混合显示。渲染子图层与拾取ContourLayer是复合层Composite Layer内部由两个子图层完成绘制见 contour-layer.tslines等值线由 PathLayer 渲染getPath取顶点序列、getColor取 contour 颜色、getWidth取strokeWidthwidthUnits: pixelsbands等值带由 SolidPolygonLayer 渲染getPolygon取多边形顶点、getFillColor取填充色。两个子图层共享同一个modelMatrix它把网格坐标平移到cellOriginCommon并按cellSizeCommon缩放再在 z 方向乘以zOffset从而把生成在网格单元整数坐标系的顶点映射回真实地理空间。拾取Pickinghover/click 事件返回的PickingInfo.object代表一条等值线或一个等值带多边形包含字段contour即传入contours的对应配置项。源码中的getPickingInfocontour-layer.ts会把拾取对象规整为{contour: ...}类型为ContourLayerPickingInfo。源码级原理Marching Squares 与聚合聚合 → 标量场无论 CPU 还是 GPU聚合的本质都是把每个数据点分配到某个网格单元并按aggregation操作合并单元值。CPU 路径在 contour-layer.ts 中将经纬度投影到公共空间按cellSizeCommon计算单元 IDGPU 路径则通过project32模块在顶点着色器中完成相同的取整计算contour-layer.ts。聚合完成后getAggregatorValueReadervalue-reader.ts把聚合结果封装为getValue(x, y)读取函数供 Marching Squares 按单元坐标取标量值。Marching Squares 生成顶点generateContourscontour-utils.ts对binIdRange范围内的每个网格单元根据四个角的单元值与阈值的比较结果生成 4 位/8 位二进制编码code再查marching-squares-codes.ts中的偏移表生成线段或多边形等值线getVertexCode中weight threshold记 1否则记 0四个角构成 4 位编码覆盖 16 种组合含鞍点情形需借助四角均值meanCode消歧等值带按weight threshold[0]/ threshold[1]/ 其他分为 0/1/2 三态构成 8 位编码每个格子可能产出多个多边形边界单元在范围外的一侧强制取 0保证生成的 contour 正确闭合。zIndex在此阶段被写入每个顶点坐标的 z 分量contour-utils.ts随后与子图层的modelMatrix一起实现三维分层。增量更新机制contour-layer.ts 展示了精心的缓存策略cellSize、gridOrigin、aggregation或数据变化时重新计算binIdRange并更新 aggregator仅contours变化时不重新聚合只把contourData置空以触发重算等值线聚合结果aggregatedValueReader保持不变。这一机制在测试中得到了明确验证。CPU vs GPU 聚合的取舍gpuAggregation默认开启但并非总是更优。聚合层 overview.md 的说明可作为选型依据数据规模CPU 聚合耗时与数据量大致线性GPU 有初始化着色器与上传缓冲的前期开销但数据量增大后边际成本很小。超过 10 万条数据时 GPU 明显更快小数据量下 GPU 反而可能更慢数据分布CPU 内存占用与含数据的单元数成正比GPU 与全部可能单元含空格子成正比因此数据密集时 GPU 更有优势扩展兼容DataFilterExtension、MaskExtension等 GPU 扩展仅与 GPU 聚合协同工作精度GPU 着色器只支持 32 位浮点虽然层内做了补偿但 GPU 与 CPU 结果未必完全一致项目内有测试保证两者在可接受范围内一致访问单元内点GPU 聚合不暴露某单元包含哪些数据点如需点击单元列出其中的位置应使用 CPU 聚合或自行过滤数据。测试验证仓库中 contour-layer.spec.ts 从多个角度验证了本示例所涉及的行为同时渲染等值线与等值带时子图层依次为PathLayer与SolidPolygonLayer更新zOffset只影响渲染、不触发重新聚合aggregatedValueReader与contourData保持不变更新cellSize会触发重新聚合与 contour 重算仅修改contours如只保留等值线或只保留等值带时聚合结果复用、只重算 contour 数据切换gpuAggregation: false会创建新的 CPU aggregator 并重算全部数据。这些测试与示例代码共同印证了上文描述的缓存与更新语义是复现、修改示例时最可靠的参考。小结examples/website/contour是一个麻雀虽小五脏俱全的 ContourLayer 参考实现它演示了数据接入COVID-19 周病例、聚合参数选择cellSize、aggregation: MAX、双模式 contour 配置等值带 等值线、动态更新updateTriggers、拾取 Tooltip 与底图混合的全部环节。配合 ContourLayer 文档 阅读源码 contour-layer.ts 与 marching-squares.ts即可将这套模式迁移到天气、人口密度、信号覆盖等任意离散点 → 连续场的可视化场景中。【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表