经纬志
首页 / deck.gl / 教程

图层类型与数据映射

先看结论

deck.gl 里没有「要素样式」这种概念,只有图层和访问器。 同一个数组,换一组访问器,就能从散点变成热力、柱体或者路径。 理解这件事,图层选型就不再靠猜。

最后验证 2026-11-03 · deck.gl 9.0 · 更新 2026-10-27 · 引用本文

所有图层共用一个模型

不论简单还是复杂,图层构造参数都分成三类:身份、数据、映射。 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)。