如何用 deck.gl 的 JSON 模块从后端下发图层配置渲染可视化
【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl
当后端已经能产出一段描述可视化的 JSON 文本时,前端可以不用为每种图层手写 JavaScript,而是用 deck.gl 的@deck.gl/json模块把这份 JSON 转换成Deck组件的 props 直接渲染。JSONConverter会按照一组@@前缀约定,把 JSON 字符串解析成 layer 类实例、React 元素、函数、常量和枚举。适用前提:前端使用 deck.gl 9.x 的安装方式(standalone bundle 或 NPM 包),并且已经了解Deck组件与图层 props 的基本概念。
准备:安装 JSON 模块
两种方式任选其一(来自 JSON 模块概览文档)。
NPM 方式:
npm install @deck.gl/core @deck.gl/layers @deck.gl/jsonimport {JSONConverter} from '@deck.gl/json';Standalone bundle 方式,页面中引入脚本后从全局deck对象上取JSONConverter:
<script src="https://unpkg.com/deck.gl@^9.0.0/dist.min.js"></script> <!-- 或者分模块引入 --> <script src="https://unpkg.com/@deck.gl/core@^9.0.0/dist.min.js"></script> <script src="https://unpkg.com/@deck.gl/layers@^9.0.0/dist.min.js"></script> <script src="https://unpkg.com/@deck.gl/json@^9.0.0/dist.min.js"></script> <!-- usage --> <script type="text/javascript"> const {JSONConverter} = deck; </script>后端下发的 JSON 描述文件要写什么
JSONConverter 文档 对 JSON 描述给出了硬性要求:
- 至少包含
layers和initialViewState两个字段; - 每个 layer 的 JSON 按 JSONLayer 格式书写,其中
@@type指定层类名。
各类引用通过@@前缀表达,完整对照见 Conversion Reference:
| 前缀 | 含义 | 示例 |
|---|---|---|
@@type | 解析为 JavaScript 类或 React 组件(在 JSONConfiguration 中查找) | "@@type": "ScatterplotLayer" |
@@function | 解析为已注册的具名函数 | "@@function": "calculateRadius" |
@@= | 把字符串解析为函数,未加引号的字符按标识符处理 | "@@=[lng, lat]" |
@@# | 解析为已注册常量 | "@@#MapController" |
@@#<enum-name>.<enum-value> | 解析为已注册枚举值 | "@@#GL.ONE" |
@@=还支持一个简单的表达式解析器,可以写布尔、内联条件和算术运算,例如"getLineColor": "@@=value > 10 ? [255, 0, 0] : [0, 255, 200]"。
一个完整的后端下发格式可以直接参考仓库中的示例 us-map.json,它演示了initialViewState、views、layers和widgets的组合:
{ "description": "A deck.gl get-started GeoJsonLayer example in JSON format", "initialViewState": { "latitude": 40, "longitude": -100, "zoom": 3, "bearing": 30, "pitch": 30 }, "map": true, "views": [ { "@@type": "MapView", "controller": true } ], "layers": [ { "@@type": "GeoJsonLayer", "data": "https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_admin_1_states_provinces_shp.geojson", "stroked": true, "filled": true, "lineWidthMinPixels": 2, "opacity": 0.4, "getLineColor": [255, 100, 100], "getFillColor": [200, 160, 0, 180] } ], "widgets": [ { "@@type": "ZoomWidget" }, { "@@type": "CompassWidget" } ] }该文件是文档给出的示例结果,其中的data地址是仓库示例自带的 GeoJSON 地址,实际下发时替换为你的数据源即可。
注册前端可用的类、函数与常量
JSON 里能出现哪些类、函数、常量,取决于你在前端通过配置对象注册的内容。JSONConfiguration 文档 列出的字段包括:
classes- 可供类解析的映射,deck.gl 场景下通常是 Layer 和 View 类;functions- 可供@@function解析的具名函数映射;enumerations- 可供字符串解析的枚举映射(按<enum-name>.<enum-value>形式解析);constants- 可供字符串解析的常量映射;reactComponents与React- React 组件解析(实验性);typeKey(默认@@type)、functionKey(默认@@function)- 判别键覆盖;convertFunction、preProcessClassProps、postProcessConvertedJson- 三个转换钩子。
最小用法(摘自 JSONConverter 文档):
const configuration = { classes: {MapView, ScatterplotLayer} };如果后端 JSON 中引用了具名函数,还要把它登记进functions。Conversion Reference 中给出的例子是:
function calculateRadius({base, exponent}) { return Math.pow(base, exponent); } const configuration = { ..., functions: {calculateRadius} };对应 JSON 中这样引用:
{ "layers": [ { "@@type": "ScatterplotLayer", "data": "此处为数据地址或数据数组,文档示例中省略为 ...", "getRadius": { "@@function": "calculateRadius", "base": 2, "exponent": 3 } } ] }如果需要开放全部图层给后端使用,仓库的 playground 示例 configuration.ts 展示了一个更完整的注册方式:把@deck.gl/core的 View、@deck.gl/layers、@deck.gl/aggregation-layers、@deck.gl/geo-layers、@deck.gl/mesh-layers、@deck.gl/carto与@deck.gl/widgets合并进classes,把@luma.gl/webgl/constants的GL注册进enumerations,并把 3D Tiles 相关 Loader 放进constants。该文件还用postProcessConvertedJson钩子在转换完成后过滤掉非法 props:
postProcessConvertedJson: (json: any) => { // Filter out invalid props. Typically, props will be invalid while the user is typing. if (json.layers) { json.layers = json.layers.filter((layer: any) => layer instanceof Layer); } // ...widgets、views 同理 return json; }这个钩子适合“配置在后端动态编辑、可能产生中间态非法值”的用法,可按需采用。配置创建后也可以用jsonConverter.mergeConfiguration({...})追加条目,不必一次注册完。
把 JSON 转换成 Deck 的 props 并渲染
主路径代码与 JSONConverter 文档 一致,json既可以是 JSON 字符串,也可以是解析后的对象;转换结果整体传给Deck:
import {JSONConverter} from '@deck.gl/json'; import {MapView} from '@deck.gl/core'; import {ScatterplotLayer} from '@deck.gl/layers'; // json 为后端下发的 JSON(字符串或已解析对象),文档示例引用本地 './us-map.json' const configuration = { classes: {MapView, ScatterplotLayer} }; const jsonConverter = new JSONConverter({configuration}); const deck = new Deck({ canvas: 'deck-canvas', json }); deck.setProps(jsonConverter.convert(json));两点执行细节:
- 完整可运行脚本中
Deck类需从@deck.gl/core导入; - 文档要求 JSON 至少含
layers与initialViewState,canvas指向页面中的画布元素 id,按需替换为你项目中的 id。
后端每次下发新的 JSON 时,只需重新执行deck.setProps(jsonConverter.convert(json)),JSON 中所有属性在处理后会作为 props 传给Deck实例。
验证转换结果与排查方法
- 看转换产物:Conversion Reference 演示了转换前后的结构对照。以 ScatterplotLayer 为例,
"@@type": "ScatterplotLayer"的 JSON 描述会被替换为new ScatterplotLayer({data, getColor, getRadius})这样的类实例。你可以在控制台打印jsonConverter.convert(json)的输出,确认layers数组里已经是类实例、@@function已被求值(上面calculateRadius示例中base: 2, exponent: 3转换后得到getRadius: 8,这是文档示例输出)。 - 未注册名称会产生警告:类名或函数名没有注册时,
JSONConverter会抛出警告("A warning will be raised if the named layer is not registered" / "A warning will be raised if the function is not registered")。看到警告先检查configuration.classes/functions是否覆盖了 JSON 中引用的名称。 - 错误检测目前有限:概览文档 明确说明 "Error detection is currently limited and error messages may not be very helpful",因此不要依赖报错信息定位配置问题,应以“转换产物 + 渲染结果”为主来核对。
限制与边界
JSONConverter只打算支持官方 deck.gl API props的 JSON 描述,文档明确说明它不会演进去支持其他 JSON schema;如果你需要自定义 schema,应基于该组件源码独立开发(见 json-converter.md 开头的 NOTE)。- 注册范围即能力范围:JSON 中出现的
@@type、@@function、@@#名称必须在configuration中登记,否则只有警告、无法实例化。
想进一步观察这个模块的实际用法,可以参考仓库中基于@deck.gl/json构建的 playground 示例 examples/playground,以及 json-examples 目录下按“JSON 版本 deck.gl 示例”组织的全部示例 payload(新增示例需登记到 index.ts,并在使用到的类时更新 playground 的 configuration)。
【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考