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

坐标数组维度不对,点全跑到南极

先看结论

数据是北京的点,图层却画在南极附近;换成另一个图层,控制台直接报顶点长度错误。

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

现象

ScatterplotLayer 的所有点都挤在南极洲外海, 或在赤道附近排成一条横线。另一个路径图层报:

Error: deck.gl: attribute positions: length 2400 is not divisible by size 3
    at Attribute.updateBuffer (attribute.js:512)

原因

deck.gl 的默认坐标顺序是 [经度, 纬度],与 GeoJSON 一致。 从数据库或 Excel 里取出的字段常是 lat, lng 顺序, 直接返回 [d.lat, d.lng],纬度 39 被当成经度, 经度 116 被当成纬度,超出 ±90 后进入异常区域。

维度问题来自 getPath 或 getPolygon:返回的数组里每个点 必须是三元组或二元组,且一致。把 [lng, lat] 与 [lng, lat, z] 混在一起,总长度就无法被整除。

排查过程

  1. 打印第一条数据的原始字段名与坐标值,确认经纬度顺序。
  2. 用 deck.pickObject 在正确位置拾取,看是否能命中,判断是坐标算错还是渲染错。
  3. 检查 getPath 返回的数组长度是否能被 3 或 2 整除。
console.log(data[0]);
// { lng: 116.391, lat: 39.907, z: null }
var p = [data[0].lat, data[0].lng];
console.log('错误写法得到的坐标', p);   // [39.907, 116.391]

解决方案

访问器统一按 [lng, lat] 返回。字段名不统一时,在数据预处理阶段改名, 不要在访问器里做判断:

var clean = raw.map(function (d) {
  return { lng: Number(d.lng || d.longitude), lat: Number(d.lat || d.latitude) };
});

new deck.ScatterplotLayer({
  id: 'stations',
  data: clean,
  getPosition: function (d) { return [d.lng, d.lat]; },
  getRadius: 8,
  radiusUnits: 'pixels'
});

只有二元坐标时,明确声明格式,避免 deck.gl 按三元组校验:

new deck.PathLayer({
  id: 'route',
  data: routes,
  getPath: function (d) { return d.path; },   // [[lng, lat], ...]
  positionFormat: 'XY',
  getWidth: 3,
  widthUnits: 'pixels'
});

轨迹带高程时,所有点都要补齐第三个分量,缺省填 0:

var path3d = route.map(function (p) {
  return [p[0], p[1], p[2] || 0];
});

new deck.PathLayer({
  id: 'route-3d',
  data: [{ path: path3d }],
  getPath: function (d) { return d.path; },
  positionFormat: 'XYZ',
  widthMinPixels: 2
});

验证

第一条点落在北京,与底图上的城市位置重合。 控制台不再出现 not divisible by size。 把 getPath 的首尾点单独打点验证,路径端点与设计坐标一致。

先看第一条:只打印 data[0] 的原始对象, 比逐条排查快得多。经纬度顺序错误是这类问题里最常见的一种,占比超过一半。

引用本文

经纬志(2026)。《坐标数组维度不对,点全跑到南极》。https://www.jingweizhi.com/cookbook/deckgl-coord-dimension.html(访问日期 2026-11-03)。