deck.gl GeoJsonLayer 多边形可视化示例实战:Vancouver 房产数据 3D 挤出渲染
deck.gl GeoJsonLayer 多边形可视化示例实战Vancouver 房产数据 3D 挤出渲染【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl本篇技术指南以当前仓库中的独立示例examples/website/geojson为核心完整讲解如何使用 deck.gl 的GeoJsonLayer将 GeoJSON 格式的面要素渲染为带 3D 挤出、光照、交互提示与底图的 WebGL2 可视化应用。读完本文你将掌握该示例的目录结构与启动方式、核心源码app.tsx的逐段配置含义、GeoJsonLayer的填充/描边/3D/点要素四大属性族以及如何替换自己的数据与底图服务并能在源码层面理解该层基于CompositeLayer的组成原理。示例定位与文件结构examples/website/geojson是 deck.gl 官方网站 GeoJsonLayerPolygons示例的最小独立版本minimal standalone version与官网示例共享同一份数据与渲染逻辑但去掉了网站外壳方便直接拷贝到自己的项目中运行。目录内共包含 5 个文件examples/website/geojson/app.tsx —— 应用主体React TypeScript 实现包含数据源、图层配置与渲染组件examples/website/geojson/index.html —— HTML 入口引入 maplibre-gl 样式并通过模块脚本挂载renderToDOMexamples/website/geojson/package.json —— 依赖与脚本声明examples/website/geojson/tsconfig.json —— TypeScript 编译配置examples/website/geojson/README.md —— 官方使用说明本文所依据的主文档。从 package.json 可以看到本示例依赖deck.gl^9.0.0聚合包、deck.gl/react、deck.gl/layers、maplibre-gl^5.0.0、react-map-gl^8.0.0、d3-scale与vite^7.3.3其 TypeScript 编译目标为es2020jsx使用react模式。快速启动三步跑起示例官方 README 给出了标准的本地运行流程将该文件夹内容复制到你的项目目录后执行# 安装依赖 npm install # 或使用 yarn yarn # 使用 vite 打包并启动开发服务器 npm startnpm start实际执行的是vite --open见 package.jsonvite 会自动打开浏览器。如果你希望在 deck.gl 仓库源码环境下运行——让 vite 通过 examples/vite.config.local.mjs 中getOcularConfig生成的别名把deck.gl/*、luma.gl/*、math.gl/*等包重定向到仓库根目录的node_modules从而直接使用本地构建产物——可以改用仓库预留的脚本npm run start-local # 等价于 vite --config ../../vite.config.local.mjs npm run build # 生产构建vite build入口加载链路为index.html中的script typemodule导入./app.tsx调用导出的renderToDOM(container)后者使用react-dom/client的createRoot将App /渲染进#app容器。数据格式与数据源示例使用的样本数据是加拿大温哥华Vancouver的地块房产价值数据数据源为 deck.gl 官方示例数据集vancouver-blocks.json其属性值由温哥华市开放数据提供。在 app.tsx 中通过常量DATA_URL远程加载该 GeoJSONconst DATA_URL https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/geojson/vancouver-blocks.json;每个 Feature 的属性结构在代码中声明为BlockProperties类型app.tsx包含三个数值字段valuePerParcel每宗地块的房产总价值valuePerSqm每平方米价值用于驱动 3D 挤出高度growth价值增长率小数形式用于驱动颜色分级。App组件的dataprop 支持两种输入字符串数据 URL或FeatureGeometry, BlockProperties[]数组app.tsx因此你可以直接把本地解析好的 GeoJSON 数组传进来。要换成自己的数据只需关注GeoJsonLayer的data属性即可。根据 GeoJsonLayer API 文档它接受以下任意格式合法的 GeoJSON 对象FeatureCollection、Feature、Geometry或GeometryCollectionGeoJSONFeature对象数组解析为上述格式的 URL 或 Promiseloaders.gl 的 flat GeoJSON 二进制格式见后文二进制数据部分。输入数据必须符合 GeoJSON 规范RFC 7946绝大多数 GIS 软件都支持导出该格式。核心源码逐段解析app.tsx3.1 色带基于 d3-scale 的阈值色标COLOR_SCALE使用d3-scale的scaleThreshold构建了一个 13 段的阈值色标app.tsx将growth增长率从 -0.6 到 1.2 的区间映射为从青绿到深红的连续色阶其中[255, 255, 204]是零值附近的浅黄色。这正是增长率越高、地块越红的经典 choropleth 配色与后续getFillColor配合使用。3.2 初始视角const INITIAL_VIEW_STATE: MapViewState { latitude: 49.254, longitude: -123.13, zoom: 11, maxZoom: 16, pitch: 45, // 45° 俯仰配合挤出体呈现立体感 bearing: 0 };视角对准温哥华市中心pitch: 45是 3D 挤出可视化常用的俯仰角。3.3 底图样式MAP_STYLE指向 CARTO 提供的免费底图服务中的positron-nolabels-gl-style样式app.tsx。nolabels 表示去掉地图标注避免与数据图层的文字提示冲突。3.4 光照与阴影示例引入了两种光源来照亮挤出体app.tsxAmbientLight环境光color: [255, 255, 255]intensity: 1.0保证模型不会被完全照亮为纯色_SunLightdeck.gl/core导出的实验性太阳光设置timestamp: Date.UTC(2019, 7, 1, 22)以计算太阳方位_shadow: true开启阴影投射。两者通过LightingEffect组合并设置shadowColor [0, 0, 0, 0.5]app.tsx经DeckGL的effectsprop 注入渲染管线。3.5 阴影承接面一个透明 PolygonLayerconst landCover: Position[][] [ [[-123.0, 49.196], [-123.0, 49.324], [-123.306, 49.324], [-123.306, 49.196]] ];代码注释明确指出这个PolygonLayerid 为ground只有在使用阴影时才需要——它是一块覆盖温哥华城区的透明平面getFillColor: [0, 0, 0, 0]、stroked: false作用是作为影子落下的地面否则阴影会投射到屏幕之外而不可见。3.6 主图层GeoJsonLayer 的完整配置new GeoJsonLayerBlockProperties({ id: geojson, data, opacity: 0.8, stroked: false, // 关闭描边挤出模式下 polygons-stroke 子层本就不会渲染 filled: true, // 开启面填充 extruded: true, // 沿 z 轴挤出为 3D 体 wireframe: true, // 显示线框网格 getElevation: f Math.sqrt(f.properties.valuePerSqm) * 10, // 高度 每平米价值的平方根 × 10 getFillColor: f COLOR_SCALE(f.properties.growth), // 颜色 增长率色标 getLineColor: [255, 255, 255], // 线框颜色为白色 pickable: true // 开启拾取配合 tooltip })值得注意的细节getElevation使用Math.sqrt压缩了价值数据的量纲差距避免个别高价值地块把其他地块压扁getLineColor在wireframe: true时充当线框颜色。这些写法是官网示例中非常典型的数据映射技巧。3.7 Tooltip拾取信息展示function getTooltip({object}: PickingInfoFeatureGeometry, BlockProperties) { return object { html: ...${object.properties.valuePerParcel} / parcel ... ${object.properties.growth} ... }; }配合pickable: true鼠标悬停地块时展示每宗地块的平均房产价值valuePerParcel、每平米价值valuePerSqm与增长率growth百分比。DeckGL的getTooltip返回含html字段的对象即可渲染自定义提示框。3.8 组装 DeckGL 与底图DeckGL layers{layers} effects{effects} initialViewState{INITIAL_VIEW_STATE} controller{true} // 开启地图交互平移/缩放/旋转 getTooltip{getTooltip} Map reuseMaps mapStyle{mapStyle} / {/* react-map-gl / maplibre 底图 */} /DeckGLcontroller: true启用内置的MapController交互react-map-gl的Map作为子组件被嵌套在DeckGL内部形成deck.gl 渲染数据图层 maplibre 渲染底图的经典组合。GeoJsonLayer 原理一个复合层CompositeLayerGeoJsonLayer并非单图层而是继承自 CompositeLayer 的复合层。从源码 geojson-layer.ts 可见其声明class GeoJsonLayer extends CompositeLayer其职责是把一份混合了 Point / LineString / Polygon 的 GeoJSON 数据拆解并分发到多个子层。子层映射定义在 sub-layer-map.ts 中核心子层包括子层 id实际图层承载的要素polygons-fillSolidPolygonLayerPolygon / MultiPolygon 的面填充polygons-strokePathLayerPolygon 轮廓线仅stroked: true且extruded: false时渲染linestringsPathLayerLineString / MultiLineStringpoints-circleScatterplotLayerPoint / MultiPointpointType含circlepoints-iconIconLayerPoint / MultiPointpointType含iconpoints-textTextLayerPoint / MultiPointpointType含text从 geojson-layer.ts 的renderLayers()可以看到图层的合成顺序未挤出时面填充层绘制在轮廓线之下挤出时面填充层最后渲染以获得正确的混合blending效果。子层的属性转发由forwardProps与sub-layer-map.ts中的 prop 映射表完成——例如getPointRadius被映射为 ScatterplotLayer 的getRadius、getTextSize被映射为 TextLayer 的getSize。更新逻辑上updateStateGeoJsonLayer 会先检测数据是否为二进制格式同时存在points、polygons、lines三个字段再分别走_updateStateBinary或_updateStateJSON两条路径geojson-layer.ts后者通过separateGeojsonFeatures按几何类型拆分要素并支持dataChanged增量更新。GeoJsonLayer 核心属性速查以下是 GeoJsonLayer API 文档 中与本文示例直接相关的属性族均已标注默认值填充Fill选项—— 控制 Polygon 面填充与 circle 点的实心填充filled默认true是否填充。注意每个多边形只填充外环与孔洞之间的区域该属性仅在未挤出时生效。getFillColor默认[0, 0, 0, 255][r, g, b, a]格式接受常量数组或按要素计算的函数。描边Stroke选项—— 控制 LineString、Polygon 轮廓与 circle 点描边stroked默认true是否绘制轮廓复杂多边形会同时绘制外环与孔洞轮廓。getLineColor默认[0, 0, 0, 255]、getLineWidth默认1单位由lineWidthUnits决定默认meters。lineWidthUnitsmeters/common/pixels三选一。lineWidthScale默认1、lineWidthMinPixels默认0防止缩小后线条过细、lineWidthMaxPixels默认Number.MAX_SAFE_INTEGER。lineCapRounded/lineJointRounded默认false、lineMiterLimit默认4、lineAntialiasing默认false、lineBillboard默认false。3D 选项—— 控制 Polygon / MultiPolygon 的挤出extruded默认false沿 z 轴挤出高度来自getElevation。getElevation默认1000单个要素的高度使用墨卡托投影模式时单位为米。elevationScale默认1最终高度 elevationScale * getElevation(d)是无需改数据即可整体缩放高度的快捷属性。wireframe默认false是否生成线框水平闭合线 每顶点竖线注意线框用GL.LINE绘制、恒为 1px且与实心挤出互斥如需叠加需建两个同数据图层仅在extruded: true时生效。material默认true作用于挤出体的光照材质设置。_full3d默认false实验性多边形三角化在面积最大的平面而非 xy 平面进行仅对含 z 值的XYZ数据有效。点要素pointType选项—— 通过pointType默认circle支持circle/icon/text可用组合如icontext切换 Point / MultiPoint 的渲染方式并分别转发到对应子层circle转发getPointRadius默认1、pointRadiusUnits默认meters、pointRadiusMinPixels/pointRadiusMaxPixels、pointAntialiasing默认true、pointBillboard默认false等到 ScatterplotLayericon转发iconAtlas、iconMapping、getIcon默认f f.properties.icon、getIconSize、getIconColor、getIconAngle、iconBillboard默认true等到 IconLayertext转发getText默认f f.properties.text、getTextColor、getTextSize默认32、getTextAnchor、getTextBackground、textFontFamily、textBillboard默认true等到 TextLayer。底层验证测试与二进制数据该示例属于多面要素 挤出场景属于 GeoJsonLayer 最核心的多边形渲染路径。仓库中对应测试见 test/modules/layers/geojson-layer.spec.ts 与 test/modules/layers/geojson-layer-webgpu.spec.ts可用于验证图层渲染结果。对于大规模数据GeoJsonLayer API 文档 还说明了二进制优化路径数据可组织为BinaryFeatureCollection顶层按points/lines/polygons分组坐标为扁平Float32Array用pathIndices/polygonIndices/primitivePolygonIndices描述线/面/孔洞的顶点偏移numericProps用类型化数组存放数值属性GeoJsonLayer 检测到该结构即走二进制渲染管线避免 JSON 解析与属性装箱开销。这也是 MVTLayer 的默认数据形态可通过 loaders.gl 的geojsonToBinary生成。底图替换方案本示例底图由 CARTO 免费底图服务提供。若需更换底图官方推荐的替代路线是改用其他底图服务如自建样式或第三方瓦片服务核心做法仍是通过react-map-gl的mapStyle传入新的样式 URL同时保持DeckGL与Map的嵌套结构不变——数据图层与底图解耦替换底图不影响任何GeoJsonLayer配置。小结examples/website/geojson是一个麻雀虽小、五脏俱全的官方示例它演示了 GeoJsonLayer 处理面要素的标准姿势——阈值色标编码数值属性、getElevation编码量级数据、extruded wireframe呈现 3D 形态、光照阴影增强立体感、tooltip 提供交互反馈。将其与 GeoJsonLayer API 文档、源码实现 对照阅读你就能把这份示例迁移到任意基于 GeoJSON 的地理数据可视化项目中。【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考