deckgl
本文回答: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自动就位;npmimport 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。
九、常见坑
- 坐标传 CAD 原值(上百万)→ Deck 直接画在"错误的地理位置"(地球外)。必须
map.toLngLat。 - 没
await map.onLoad:直接 addLayer 会失败。 - Deck script 未加载完就 new:通过
typeof deck !== "object"守卫。 - Deck 图层遮挡交互:
pickable: true时会拦截 mousemove,导致 vjmap 自己的 hover 不触发。