图层类型与数据映射
deck.gl 里没有「要素样式」这种概念,只有图层和访问器。 同一个数组,换一组访问器,就能从散点变成热力、柱体或者路径。 理解这件事,图层选型就不再靠猜。
所有图层共用一个模型
不论简单还是复杂,图层构造参数都分成三类:身份、数据、映射。
id 决定更新时是否复用,data 决定画什么,
以 get 开头的访问器决定每一条数据长成什么样。
new deck.ScatterplotLayer({
id: 'stations', // 身份
data: stations, // 数据
getPosition: function (d) { return [d.lng, d.lat]; },
getRadius: function (d) { return Math.sqrt(d.flow) * 2; },
getFillColor: [40, 140, 255, 180]
})
按职责分四类
| 类别 | 代表图层 | 适用场景 |
|---|---|---|
| 单要素图层 | ScatterplotLayer、PathLayer、PolygonLayer、ColumnLayer、IconLayer、TextLayer、ArcLayer | 几何简单、条数在十万级以内,需要逐条控制颜色和尺寸 |
| 聚合图层 | HeatmapLayer、HexagonLayer、GridLayer、ScreenGridLayer、ContourLayer | 数据太密看不清单点,先把空间单元统计出来再画 |
| 复合图层 | GeoJsonLayer、TextLayer、TileLayer、MVTLayer | 一个图层内部再生成若干子图层,按几何类型分别渲染 |
| 三维与网格 | SimpleMeshLayer、PointCloudLayer、TerrainLayer | 模型、点云、地形表面 |
聚合图层不是「另一种画法」,而是多了一步 GPU 统计:先把每个点归入空间单元,
算出单元内的计数或权重和,再对单元着色。因此它的坐标单位必须是真实距离(米),
radius、cellSize 这类参数写成像素是没有意义的。
访问器返回什么
访问器接收一条数据,返回一个值。返回值类型由图层定义,写错类型不会报错, 只会静默画出空白。
| 访问器 | 返回 | 示例 |
|---|---|---|
getPosition | [经度, 纬度],可选第三位为高度 | [116.39, 39.90] |
getFillColor | [r, g, b, a],0–255 | [255, 120, 40, 200] |
getRadius / getWidth | 数字,单位由 radiusUnits / widthUnits 决定 | 12 |
getPath | 坐标数组的数组 | [[116.1, 39.7], [116.5, 39.9]] |
getPolygon | 顶点数组;多环时用嵌套数组,首环为外环 | [[ [x, y], [x, y] ]] |
getElevation | 数字,米 | 220 |
颜色也可以直接给常量数组,这时它不再是函数,所有要素同色。 返回十六进制字符串是行不通的,WebGL 只认数值通道。
updateTriggers 是必须掌握的开关
deck.gl 只在图层重建或数据变化时重新求值访问器。如果你依赖外部变量
(比如配色方案、时间帧、筛选阈值),就必须通过 updateTriggers
告诉它「这个访问器的结果变了」。
var opts = { scheme: 'flow' };
function fill(d) {
return opts.scheme === 'flow' ? [30, 144, 255, 200] : [255, 165, 0, 200];
}
function buildLayer() {
return new deck.ScatterplotLayer({
id: 'stations',
data: stations,
getPosition: function (d) { return [d.lng, d.lat]; },
getFillColor: fill,
updateTriggers: {
getFillColor: opts.scheme // 值变则重算,值同则跳过
}
});
}
updateTriggers 的值可以是任意可比较的标量或对象。
漏写的表现很典型:数据没刷新,但界面上的颜色停在旧值,拖动一下才偶尔恢复。
复合图层内部发生了什么
GeoJsonLayer 收到一个 FeatureCollection 后,会按几何类型拆开:
面走 PolygonLayer,线走 PathLayer,点走
ScatterplotLayer。所以它的 getFillColor 只对
面生效,getLineColor 对线和面边界都生效。点要素需要单独用
pointType 指定渲染方式,否则默认画成圆点。
这也解释了为什么复合图层的拾取结果里,info.object 可能是
Feature、也可能是 Feature 里的 geometry —— 取决于命中的子图层。
需要稳定拿到属性时,读 info.object.properties 之前先判空。
图层顺序与混合
layers 数组的顺序就是绘制顺序,后画的盖住先画的。
透明图层叠加时结果依赖混合模式,默认的 alpha 混合在大量半透明面叠加后
会显得发灰;需要更干净的叠加时,把透明度集中到一个图层上,
而不是多层半透明堆叠。
常见错误
访问器每次都返回新数组
getPosition: function (d) { return [d.lng, d.lat]; }
每次求值都新建数组,数据量大时会产生大量短命对象。
数据准备阶段把坐标预先算好存成 d.position,访问器直接
return d.position,可以省掉这部分开销。
把对象当成坐标
{lng: 116, lat: 39} 不能直接返回给 getPosition。
deck.gl 只认数组,遇到对象会得到 NaN 坐标,画面全空且控制台无提示。
用聚合图层画稀疏数据
只有几十个点时,HexagonLayer 会把它们全部塞进一两个格子里,
得到一块没有信息量的色斑。聚合图层的价值在密度,不在数量。
经纬志(2026)。《图层类型与数据映射》。https://www.jingweizhi.com/deckgl/tutorial/layers.html(访问日期 2026-11-03)。