唯杰地图 logo唯杰地图
VJMAP
EN

deckgl

vjmap/references/overlay/deckgl.md 4.5 KB153 行
原文

本文回答:vjmap + Deck.GL 集成方式 —— 加脚本、创建 DeckLayer、数据坐标。

一、加载 deck.gl

Deck.GL 通过动态脚本加载:

if (typeof deck !== "object") {
  await vjmap.addScript({ src: "js/deck.gl.min.js" });
}

或 npm:

npm i deck.gl @deck.gl/layers
import { ArcLayer, ScatterplotLayer } from "@deck.gl/layers";

vjmap 提供 vjmap.DeckLayer 适配器,把 Deck.GL 图层包装成 vjmap 可识别的自定义图层,推荐直接用它(见下节)。

二、通过 vjmap.DeckLayer 集成

const deckLayer = new vjmap.DeckLayer({
  id: "deck",
  type: deck.ArcLayer,
  data: [
    { from: { coord: [116.3, 39.9] }, to: { coord: [117.3, 40.9] } }
  ],
  getWidth: 12,
  getSourcePosition: d => d.from.coord,
  getTargetPosition: d => d.to.coord,
  getSourceColor: [255, 0, 0],
  getTargetColor: [0, 255, 0],
  pickable: true,
  autoHighlight: true,
  onClick: ({ object }) => alert("第 " + object.id)
});
map.addLayer(deckLayer);

坑位(deck 命名空间来源):构造函数实际读 window.deck ?? props.deck——不是 props.deckNs(d.ts 的 deckNs 字段名有误导性,传入无效)。用 script 标签加载 deck.gl UMD 时 window.deck 自动就位;npm import deck 的用户必须显式传 deck 属性:

import * as deck from "deck.gl"; // 传 deck.gl 元包的完整命名空间;只引入 @deck.gl/core、@deck.gl/layers 等子包不够
new vjmap.DeckLayer({ id: "d", deck, type: deck.ArcLayer, /* ... */ });

两者都没有时构造即抛 Cannot read properties of undefined。

三、完整示例(弧线图)

const svc = new vjmap.Service(URL, TOKEN);
const res = await svc.openMap({ mapid: "sys_zp", mapopenway: vjmap.MapOpenWay.GeomRender, style: vjmap.openMapDarkStyle() });
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromString(res.bounds));

const map = new vjmap.Map({
  container: "map",
  style: svc.rasterStyle(),
  center: prj.toLngLat(prj.getMapExtent().center()),
  zoom: 2, pitch: 60,
  renderWorldCopies: false
});
map.attach(svc, prj);
await map.onLoad();

if (typeof deck !== "object") await vjmap.addScript({ src: "js/deck.gl.min.js" });

// 10 条随机弧线(坐标转到渲染经纬度)
const bounds = map.getGeoBounds(0.6);
const data = [];
for (let i = 0; i < 10; i++) {
  data.push({
    id: i + 1,
    from: {
      coordinates: map.toLngLat(bounds.randomPoint()),
      color: [vjmap.randInt(0,255), vjmap.randInt(0,255), vjmap.randInt(0,255)]
    },
    to: {
      coordinates: map.toLngLat(bounds.randomPoint()),
      color: [vjmap.randInt(0,255), vjmap.randInt(0,255), vjmap.randInt(0,255)]
    }
  });
}

const deckLayer = new vjmap.DeckLayer({
  id: "deck",
  type: deck.ArcLayer,
  data,
  getWidth: 12,
  getSourcePosition: d => d.from.coordinates,
  getTargetPosition: d => d.to.coordinates,
  getSourceColor: d => d.from.color,
  getTargetColor: d => d.to.color,
  pickable: true,
  autoHighlight: true
});
map.addLayer(deckLayer);

四、常见 Deck 图层

图层 用途
ScatterplotLayer 散点(可交互)
ArcLayer 弧线
LineLayer 直线
PolygonLayer 多边形
HexagonLayer 蜂窝聚合
HeatmapLayer 热力图
TripsLayer 时序轨迹动画
ColumnLayer 3D 柱状
PathLayer 路径

五、数据坐标

Deck.GL 默认使用 经纬度 [lng, lat]。所以 CAD 坐标要:

const deckPoints = cadPoints.map(p => map.toLngLat(p));

六、3D / 俯仰角

Deck.GL 支持 pitch,但必须 map.getPitch() > 0。

const map = new vjmap.Map({ ..., pitch: 60 });

七、与 vjmap 样式协同

  • Deck 图层默认在 vjmap 所有层之上。
  • 通过 map.addLayer(deckLayer, beforeId) 插入到指定位置。

八、性能

  • 大数据量(>10 万点)用 HexagonLayer / HeatmapLayer 聚合。
  • 开 pickable: false 不交互时快很多。
  • 关闭 autoHighlight。

九、常见坑

  1. 坐标传 CAD 原值(上百万)→ Deck 直接画在"错误的地理位置"(地球外)。必须 map.toLngLat。
  2. 没 await map.onLoad:直接 addLayer 会失败。
  3. Deck script 未加载完就 new:通过 typeof deck !== "object" 守卫。
  4. Deck 图层遮挡交互:pickable: true 时会拦截 mousemove,导致 vjmap 自己的 hover 不触发。