拾取与交互
deck.gl 的拾取不是命中测试,而是把每个图元编码成颜色再读回来。 因此默认所有图层都不可拾取,要显式打开,并且每帧的拾取都有成本。
打开拾取并绑定回调
图层默认 pickable: false。打开后,onClick、
onHover、onDrag 这些回调才会收到该图层的信息。
回调参数是一个 info 对象,info.object 是命中的那条数据。
var stationsLayer = new deck.ScatterplotLayer({
id: 'stations',
data: stations,
getPosition: function (d) { return [d.lng, d.lat]; },
getRadius: function (d) { return d.flow > 800 ? 10 : 6; },
getFillColor: [40, 140, 255, 200],
pickable: true,
autoHighlight: true,
highlightColor: [255, 200, 0, 220],
onClick: function (info) {
console.log('点击', info.object.name, '索引', info.index);
},
onHover: function (info) {
document.body.style.cursor = info.object ? 'pointer' : 'default';
}
});
new deck.Deck({
container: 'map',
initialViewState: {
longitude: 116.397,
latitude: 39.908,
zoom: 11,
pitch: 0
},
controller: true,
pickingRadius: 6,
layers: [stationsLayer]
});
autoHighlight 是 deck.gl 内置的悬停高亮,按图层 id 记录当前命中对象,
不需要自己维护状态。highlightColor 的 alpha 决定覆盖强度。
| 字段 | 含义 | 备注 |
|---|---|---|
info.object | 命中的数据项 | 未命中时为 null |
info.index | 数据在数组中的下标 | 聚合图层为 -1 |
info.layer | 命中的图层实例 | 可用于判断来自哪一层 |
info.coordinate | 地理坐标 | [经度, 纬度, 高度] |
info.x / info.y | 画布像素坐标 | 用于放置提示框 |
info.picked | 是否命中 | 部分图层会返回额外信息 |
多层叠加时的拾取顺序
拾取按图层绘制顺序从后往前查,最上层的命中优先返回。
如果上层图层完全透明或 pickable: false,会继续往下找。
这也是「底图盖住了业务图层就点不到」的最常见原因。
var layers = [
new deck.GeoJsonLayer({
id: 'parcels',
data: parcels,
filled: true,
pickable: true,
onClick: function (info) { console.log('地块', info.object.properties.id); }
}),
new deck.ScatterplotLayer({
id: 'stations',
data: stations,
getPosition: function (d) { return [d.lng, d.lat]; },
getRadius: 7,
pickable: true
})
];
// Deck 级回调只在所有图层都未命中时触发
var deckgl = new deck.Deck({
container: 'map',
initialViewState: { longitude: 116.397, latitude: 39.908, zoom: 11 },
controller: true,
layers: layers,
onClick: function (info, event) {
if (!info.object) console.log('空白处', info.coordinate);
}
});
图层回调先于 Deck 回调执行。同一次点击,两层都命中时只会调用最上层图层的
onClick,Deck 级回调拿到的仍是这次命中的 info。
拾取半径影响容差。pickingRadius: 6 让指针周围 6 像素内都算命中,
适合细线和小点。数值过大会让相邻要素互相抢命中,悬停高亮来回跳。
悬停的代价
每次指针移动都会触发一次离屏拾取渲染。十万级散点图开着 onHover
时,帧率下降非常明显。常见做法是只在需要提示的图层打开拾取,
其余图层保持 pickable: false,并用 autoHighlight
代替手写悬停逻辑。
注意事项
- 图层的
id必须稳定。每次渲染都换 id 会让 deck.gl 重建图层,拾取状态随之丢失。 - 聚合图层的
info.object是聚合结果对象,不是原始数据项;原始点存放在info.object.points里。 - 给
onClick传箭头函数时,若依赖外部变量,要确认每次渲染都能拿到最新值。 - 画布尺寸为 0(容器未挂载或隐藏)时拾取全部失效,控制台不会有提示。
- 移动端触摸事件的坐标是 CSS 像素,
info.x / info.y与之一致,可直接用于定位提示框。
经纬志(2026)。《拾取与交互》。https://www.jingweizhi.com/deckgl/tutorial/picking.html(访问日期 2026-11-03)。