经纬志
首页 / 实战手册 / deck.gl 可视化

点了地图,拾取永远是 null

先看结论

鼠标明明停在点上,onClick 里的 info.object 一直是空值, 只有 info.index 有时是 -1。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

图层显示正常,点击事件也触发了,但回调参数是:

{ color: null, index: -1, picked: false, x: 412, y: 337, object: null, layer: null }

原因

deck.gl 的拾取是额外的渲染通道,只有声明 pickable: true 的图层才参与。 默认值是 false,这是最常见的原因。

其次是遮挡:在同一个位置上叠了一层铺满全屏的底图图层, 即使它没有数据,也会先被拾取到,导致下层目标图层拿不到事件。 pickingRadius 设为很大的值同样会误拾取邻近要素。

与 MapLibre 组合时,如果 deck.gl 的画布不是最上层,点击会先被地图 canvas 接收, 需要 interleaved: false 或调整容器层级。

排查过程

绕开鼠标事件,直接用坐标做一次拾取,快速判断是图层问题还是事件链路问题:

var info = deck.pickObject({ x: 412, y: 337, radius: 4 });
console.log(info && info.layer ? info.layer.id : 'no layer', info && info.object);

如果能拾取到,问题在事件绑定;如果拾取不到,问题在图层配置。 再打印所有图层的 pickable 与 visible:

deck.layerManager.getLayers().forEach(function (l) {
  console.log(l.id, l.props.pickable, l.props.visible, l.props.coordinateSystem);
});

解决方案

给需要交互的图层显式开启拾取,并限制拾取半径:

var layer = new deck.ScatterplotLayer({
  id: 'stations',
  data: stations,
  getPosition: function (d) { return [d.lng, d.lat]; },
  getRadius: 10,
  radiusUnits: 'pixels',
  pickable: true,          // 必须
  autoHighlight: true,
  highlightColor: [255, 255, 0, 180]
});

var overlay = new deck.MapboxOverlay({
  layers: [layer],
  pickingRadius: 5
});
map.addControl(overlay);

overlay.setProps({
  onClick: function (info) {
    if (!info.object) return;
    console.log('选中', info.object.name, '图层', info.layer.id);
  }
});

被上层图层遮挡时,把纯装饰图层关掉拾取,或用 pickable 只留给数据图层:

var background = new deck.PolygonLayer({
  id: 'background',
  data: [boundary],
  getPolygon: function (d) { return d.coordinates; },
  filled: true,
  pickable: false         // 不参与拾取,避免抢占
});

需要在拾取时拿到原始业务对象,用 getObject 或直接传对象本身, 不要让 data 只存坐标数组:

new deck.IconLayer({
  id: 'poi',
  data: pois,                       // 保留完整对象
  getPosition: function (d) { return [d.lng, d.lat]; },
  getIcon: function () { return { url: '/icons/poi.png', width: 32, height: 32 }; },
  pickable: true
});

验证

点击任意一个点,info.object 返回对应记录,info.layer.id 正确。 点在空白处返回 null,不误报邻近要素。 开启 autoHighlight 后,悬停的点有明显高亮反馈。

排查顺序:先 pickObject 再查事件、先查 pickable 再查遮挡。三层里任意一层没配对,表现都是同一个 object: null。

引用本文

经纬志(2026)。《点了地图,拾取永远是 null》。https://www.jingweizhi.com/cookbook/deckgl-pick-fail.html(访问日期 2026-11-03)。