数据源与二进制属性
同一批点可以用对象数组、GeoJSON 或二进制缓冲三种方式交给图层。 前两种写起来快,第三种省内存和解析时间,选择取决于数据规模与更新频率。
| 形态 | 写法 | 优点 | 适用 |
|---|---|---|---|
| 对象数组 | data: [{lng, lat}] | 直观,访问器直接读字段 | 几千到几万条 |
| GeoJSON | data: featureCollection | 带几何与属性,图层自动解析 | 面与线、需要保留属性 |
| CSV | loaders.gl 解析后得到对象数组 | 业务数据导出方便 | 表格类点位 |
| 二进制属性 | {length, attributes} | 无对象开销,上传显存快 | 十万级以上 |
二进制属性怎么写
二进制数据不是另一种图层,而是给图层换一种 data 结构。
属性名与图层属性同名,size 表示每条数据占几个分量,
value 是一个类型化数组。
var N = stations.length;
var positions = new Float32Array(N * 2);
var radii = new Float32Array(N);
var colors = new Uint8Array(N * 4);
for (var i = 0; i < N; i++) {
positions[i * 2] = stations[i].lng;
positions[i * 2 + 1] = stations[i].lat;
radii[i] = stations[i].flow > 800 ? 9 : 5;
colors[i * 4] = 40;
colors[i * 4 + 1] = 140;
colors[i * 4 + 2] = 255;
colors[i * 4 + 3] = 200;
}
var binaryData = {
length: N,
attributes: {
getPosition: { value: positions, size: 2 },
getRadius: { value: radii, size: 1 },
getFillColor: { value: colors, size: 4 }
}
};
new deck.ScatterplotLayer({
id: 'stations-binary',
data: binaryData,
radiusUnits: 'pixels',
pickable: true
});
二进制模式下不再需要写 getPosition 这类访问器,
图层直接读取属性缓冲。写错 size 不会报错,只会看到位置错乱或颜色异常。
数组长度必须够。N * size 少了任何一个分量都会读到 undefined,
表现为最后一个要素位置为 0。构造完先打印 positions.length 核对。
CSV 与 GeoJSON 的加载
CSV 不会自动带坐标,需要先解析成对象数组,再在访问器里转成数值。
字符串直接参与位置计算会得到 NaN。
import { load } from '@loaders.gl/core';
import { CSVLoader } from '@loaders.gl/csv';
const rows = await load('/data/stations.csv', CSVLoader);
new deck.ScatterplotLayer({
id: 'stations-csv',
data: rows,
getPosition: function (d) {
return [Number(d.lng), Number(d.lat)];
},
getRadius: 6,
radiusUnits: 'pixels'
});
// GeoJSON 直接交给复合图层,几何与属性都由它解析
new deck.GeoJsonLayer({
id: 'districts',
data: '/data/districts.geojson',
filled: true,
getFillColor: [31, 95, 208, 60],
getLineColor: [31, 95, 208, 220]
});
用扩展做 GPU 过滤
按阈值筛选时,常见做法是过滤数组后重建图层,数据一变就要重新上传缓冲。
DataFilterExtension 把筛选条件传给着色器,滑动阈值时不需要重建数据。
import { DataFilterExtension } from '@deck.gl/extensions';
var filter = new DataFilterExtension({ filterSize: 1 });
var layer = new deck.ScatterplotLayer({
id: 'stations-filtered',
data: stations,
getPosition: function (d) { return [d.lng, d.lat]; },
getRadius: 6,
radiusUnits: 'pixels',
getFilterValue: function (d) { return d.flow; },
filterRange: [500, 2000],
extensions: [filter],
updateTriggers: {
getFilterValue: flowDomain
}
});
// 只改阈值,数据与缓冲都不动
layer.setProps({ filterRange: [1200, 2000] });
filterSize 决定每条数据有几个筛选维度。二维筛选(比如同时限制流量与距离)时
把 size 设为 2,访问器返回两个数的数组。
注意事项
- 二进制属性的
value必须是类型化数组,普通数组不会走快速路径。 - 数据对象变化后要更换
data引用,原地修改类型化数组不会触发更新。 - GeoJSON 的属性读取要经过
feature.properties,访问器里直接读d.flow会得到undefined。 - CSV 解析出的数字是字符串还是数值取决于加载器配置,必要时统一
Number()转换。 - 过滤扩展只影响显示与拾取,不影响图层内部统计,聚合图层的权重仍需自行处理。
先统一坐标再谈格式。不管来自哪种数据源,进入图层前都应该先转成
[经度, 纬度] 数组。坐标预处理一次,比在每个访问器里转换更省心。
经纬志(2026)。《数据源与二进制属性》。https://www.jingweizhi.com/deckgl/tutorial/data-formats.html(访问日期 2026-11-03)。