@ deckgl-fiber-resters/dom (英语)
甲板反射渲染器 利用React组件和钩子来构建地理空间可视化,并配有完整的TypeScript支持.
安装
pnpm add @deckgl-fiber-renderer/dom
同伴依赖关系
pnpm add react react-dom @deck.gl/core @deck.gl/layers
所需经费: 反应 19.0.0+, 甲板. gl 数据 ^9.1.0
教学
您的第一个地图
构建3个步骤的可工作散点可视化.
1. 创建该部分
import { Deckgl } from "@deckgl-fiber-renderer/dom";
import { ScatterplotLayer } from "@deck.gl/layers";
function App() {
const data = [
{ position: [-122.45, 37.8], size: 100, name: "Point A" },
{ position: [-122.46, 37.81], size: 200, name: "Point B" },
];
return (
<Deckgl
initialViewState={{
longitude: -122.45,
latitude: 37.8,
zoom: 12,
}}
style={{ width: "100%", height: "100vh" }}
>
<layer
layer={
new ScatterplotLayer({
id: "points",
data,
getPosition: (d) => d.position,
getRadius: (d) => d.size,
getFillColor: [255, 140, 0],
})
}
/>
</Deckgl>
);
}
2. 增加互动性
import { useState } from "react";
function App() {
const [hovered, setHovered] = useState(null);
return (
<Deckgl
initialViewState={{ longitude: -122.45, latitude: 37.8, zoom: 12 }}
onHover={(info) => setHovered(info.object)}
getCursor={() => (hovered ? "pointer" : "grab")}
>
<layer
layer={
new ScatterplotLayer({
id: "points",
data,
getPosition: (d) => d.position,
getRadius: (d) => d.size,
getFillColor: hovered ? [255, 200, 0] : [255, 140, 0],
pickable: true,
})
}
/>
{hovered && <div className="tooltip">{hovered.name}</div>}
</Deckgl>
);
}
3. 成功标准
- 在地图上看到橙色点
- 盘旋时的光标变化
- QQ 工具提示显示点名
更多关于甲板. gl 层: https://deck.gl/docs/api-参考资料/层
如何向导
与 MapLibre/ Mapbox 合并
使用间叶渲染来将甲板.gl和基底映射层结合.
import { Map, useControl } from "react-map-gl/maplibre";
import { Deckgl, useDeckgl } from "@deckgl-fiber-renderer/dom";
function DeckglOverlay() {
const deck = useDeckgl();
useControl(() => deck);
return null;
}
function App() {
return (
<Map
initialViewState={{ longitude: -122.4, latitude: 37.8, zoom: 12 }}
mapStyle="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
>
<Deckgl interleaved>
<DeckglOverlay />
<layer layer={new ScatterplotLayer({ id: "points", data })} />
</Deckgl>
</Map>
);
}
要点:
<Map>包装<Deckgl>,反之亦然interleaved道具允许层相交useDeckgl()提供甲板实例给useControl()
学习更多: https://deck.gl/docs/api-reference/mapbox/overview 页面存档备份,存于互联网档案馆
渲染多视图
用不同的相机分割屏幕或微型相机 .
import { MapView, OrthographicView } from "@deck.gl/core";
function App() {
return (
<Deckgl>
<view
view={
new MapView({
id: "main",
x: 0,
y: 0,
width: "70%",
height: "100%",
})
}
>
<layer layer={new ScatterplotLayer({ id: "main-points", data })} />
</view>
<view
view={
new OrthographicView({
id: "minimap",
x: "70%",
y: 0,
width: "30%",
height: "100%",
})
}
>
<layer layer={new ScatterplotLayer({ id: "mini-points", data })} />
</view>
</Deckgl>
);
}
说明: 通过视图过滤层需要通过道具进行人工控制. 所有层默认在所有视图中渲染 .
学习更多: https://deck.gl/docs/api-reference/core/deck#views 页面存档备份,存于互联网档案馆
使用自定义图层
自定义层在没有注册的情况下立即工作 .
import { CompositeLayer } from "@deck.gl/core";
import { ScatterplotLayer } from "@deck.gl/layers";
class CustomLayer extends CompositeLayer {
static layerName = "CustomLayer";
renderLayers() {
return new ScatterplotLayer({
id: `${this.props.id}-scatter`,
data: this.props.data,
getPosition: (d) => d.coordinates,
getRadius: this.props.customRadius || 100,
});
}
}
// Use immediately - no registration needed
<layer layer={new CustomLayer({ id: "custom", data, customRadius: 200 })} />;
类型脚本打字( 可选) :
type CustomLayerProps = {
id: string;
data: unknown[];
customRadius?: number;
};
declare global {
namespace React.JSX {
interface IntrinsicElements {
customLayer: CustomLayerProps;
}
}
}
// Now <customLayer> has type checking (but <layer> is recommended)
学习更多: https://deck.gl/docs/developer-guide/海关一级
参考文献
API : (英语) <Deckgl>
Root容器用于甲板.gl可视化.
<Deckgl
initialViewState={{ longitude: -122.4, latitude: 37.8, zoom: 12 }}
width="100%"
height="100vh"
onLoad={(deck) => console.log("Ready", deck)}
>
{children}
</Deckgl>
道具 :
| Prop | 类型 | 说明 |
|---|---|---|
initialViewState | object | 初始相机位置(经度、纬度、缩放等) |
width | string | number | 容器宽度( 支持 CSS 值) |
height | string | number | 集装箱高度(支持CSS值) |
interleaved | boolean | 启用用于 Basemap 集成的相叶渲染 |
onLoad | (deck: Deck) => void | 甲板. gl 初始化时召回 |
onViewStateChange | (params) => void | 视图状态改变时召回 |
onHover | (info, event) => void | 盘旋时召回 |
onClick | (info, event) => void | 点击后调用 |
getCursor | (state) => string | 基于状态的自定义光标 |
debug | boolean | 启用日志( 只开发模式) |
继承道具: 所有道具从甲板。 GL's (英语) DeckProps 财务报告和审定财务报表 MapboxOverlayProps 被支持.
API : (英语) useDeckgl()
钩子进入甲板. gl实例.
import { useDeckgl } from "@deckgl-fiber-renderer/dom";
function MyComponent() {
const deck = useDeckgl();
useEffect(() => {
if (deck) {
console.log("Current view state:", deck.viewState);
}
}, [deck]);
return null;
}
回返情况: Deck | null
说明: 回返 null 直至 <Deckgl> 上马 使用前总是检查.
API : (英语) <layer> 财务报告和审定财务报表 <view>
层和视图的通用元素(v2语法).
<layer> 元素 :
<layer layer={new ScatterplotLayer({ id: "points", data })} key="optional-react-key" />
| Prop | 类型 | 需求 | 说明 |
|---|---|---|---|
layer | Layer | 对 | 甲板.gl (英语). 图层实例 |
key | string | 没有 | 列表渲染的响应密钥 |
<view> 元素 :
<view view={new MapView({ id: "main" })} key="optional-react-key" />
| Prop | 类型 | 需求 | 说明 |
|---|---|---|---|
view | View | 对 | deck.gl 视图实例 |
key | string | 没有 | 列表渲染的响应密钥 |
类型脚本通用名 :
type DataPoint = { coordinates: [number, number]; value: number };
<layer
layer={
new ScatterplotLayer<DataPoint>({
id: "points",
data,
getPosition: (d) => d.coordinates, // d typed as DataPoint
getRadius: (d) => d.value, // Full autocomplete
})
}
/>;
API : (英语) extend() (折旧)
import { extend } from "@deckgl-fiber-renderer/dom";
import { MyCustomLayer } from "./my-custom-layer";
extend({ MyCustomLayer });
// Deprecated - use <layer> instead
<myCustomLayer id="custom" data={data} />;
折旧: 此函数已贬值,将在 v3 中被删除 。 使用 <layer layer={new MyCustomLayer(...)} /> 换句话说.
解释
为什么是反应器?
官方甲板.gl React 绑定了必须的甲板.gl API. 这种限制成分——分层必须是直生子,钩子不起作用,而TypeScript generals是不支持的.
反应调和器在更低的级别集成了deck.gl. 它教 React 如何渲染到 jadle.gl, 使地层一级 React 组件. 这样可以:
- 缠绕 - 层层可以在您组件树的任何地方
- 钩子 - 使用状态,使用Context,自定义钩 全部工作
- 常规 - 进入器函数中的全部类型Script类型推论
- 组成 - 建立可重复使用的层组件
权衡: 稍大的捆绑(~15KB)用于调节器基础设施. 值得团队建立复杂的视觉.
持久性模式设计
反应调和器可以变异节点(DOM)或取而代之(原始语如字符串). 此调节器使用 持久性模式 - 它取代了地层,而不是改变它们.
为什么? deck.gl地层被设计为可永恒的描述:
"Layers是描述对象,非常便宜,可以即时使用. 每个渲染周期都创造出一套新的地层 deck.gl 文档
deck.gl 处理内部高效更新 :
- 以 ID 匹配层
- 抖道道具
- 重用 GPU 资源
调和器在道具变化上创建了新的层例. date.gl的抖动算法检测到实际变化,仅更新了受影响的状态.
性能 : 无上行. 创建层例是便宜的 - 它们只是普通对象,直到甲板.gl处理它们.
层 ID 和 diffing
规则: 总是提供清晰的,稳定的 id 道具来.
// ✅ Good - explicit, stable ID
<layer layer={new ScatterplotLayer({ id: "points", data })} />
// ❌ Bad - missing ID (auto-generated, changes every render)
<layer layer={new ScatterplotLayer({ data })} />
// ❌ Bad - non-stable ID (changes every render)
<layer layer={new ScatterplotLayer({ id: Math.random().toString(), data })} />
为什么? deck.gl使用ID进行分解. 没有稳定的身份证:
- 每层都被视为新出土
- GPU 资源被销毁并重建
- 动画重置
- 性能降低
开发模式验证 : 缺少或重复ID触发警告. 这些检查从生产建筑中剥离.
学习更多: https://deck.gl/docs/developer-guide/using-layers#layer-dentity-and-diffing 互联网档案馆的存檔,存档日期2013-12-22
v1 vs v2 语法
理解 v1 自动注册
在 v1 中, 导入副作用模块会自动注册所有 deck. gl 层 :
// v1 side-effects import (no longer works in v2)
import "@deckgl-fiber-renderer/reconciler/side-effects";
此单导入已执行代码 extend() 有30多层构造器:
// What the v1 side-effects import did internally:
extend({
// Views
MapView,
OrthographicView,
OrbitView,
FirstPersonView,
GlobeView,
// @deck.gl/layers (13 layers)
ArcLayer,
BitmapLayer,
IconLayer,
LineLayer,
PointCloudLayer,
ScatterplotLayer,
ColumnLayer,
GridCellLayer,
PathLayer,
PolygonLayer,
GeoJsonLayer,
TextLayer,
SolidPolygonLayer,
// @deck.gl/geo-layers (14 layers)
S2Layer,
QuadkeyLayer,
TileLayer,
TripsLayer,
H3ClusterLayer,
H3HexagonLayer,
Tile3DLayer,
TerrainLayer,
MVTLayer,
GeohashLayer,
GreatCircleLayer,
WMSLayer,
// @deck.gl/mesh-layers (2 layers)
ScenegraphLayer,
SimpleMeshLayer,
});
注册后,您可以使用特定层次的JSX元素:
<scatterplotLayer id="points" data={data} getPosition={(d) => d.coordinates} />
<pathLayer id="routes" data={routes} getPath={(d) => d.path} />
* 移徙脚枪
JSX元素在v2中仍然有TypeScript类型,但没有适当的注册,它们不会在运行时间工作.
这是最常见的迁移错误:
// No registration - JSX types exist but runtime catalog is empty
<scatterplotLayer id="points" data={data} getPosition={(d) => d.coordinates} />
// ^^^^^^^^^ TypeScript: ✅ Runtime: ❌ "Unknown element type: scatterplotLayer"
为什么会这样:
- 类型脚本存在 :
@deckgl-fiber-renderer/types声明所有层的 JSX 元素的后向兼容性 - 运行时注册为空 : 没有手动
extend()电话,调和器不知道如何即兴演奏scatterplotLayer - 副作用导入为 v2 中的无操作 : 它只显示一个腐烂的警告 - 它不再记录层
- 类型脚本无法抓取 : 类型定义不能保证运行时的行为
哪些断层 :
- 您的应用程序不做任何更改或显示错误
- 地图上没有层
- 控制台显示“ 未知元素类型” 错误
移徙战略
备选案文1:迁移到 v2 语法(建议)
用通用 <layer> 元素 :
// ✅ v2 - No registration needed
import { ScatterplotLayer } from "@deck.gl/layers";
<layer
layer={
new ScatterplotLayer({
id: "points",
data,
getPosition: (d) => d.coordinates,
})
}
/>;
福利:
- * 无需登记 -- -- 立即工作
- * ** 带有类型推论的完整类型脚本通用词
- QQ 自动代码分割( 只捆绑导入的层)
- QQ 自定义层工作, 不设置
- * 未来防(v3中去掉的v1语法)
备选案文2:坚持v1语法(不建议)
如果您必须临时停留在 v1 语法上, 您需要使用手动注册层 extend()。 。 。 .
用于完整 v1 行为 (所有默认层):
// Recreate v1 side-effects behavior manually
import { extend } from "@deckgl-fiber-renderer/dom";
import {
FirstPersonView,
_GlobeView as GlobeView,
MapView,
OrbitView,
OrthographicView,
} from "@deck.gl/core";
import {
GeohashLayer,
GreatCircleLayer,
H3ClusterLayer,
H3HexagonLayer,
MVTLayer,
QuadkeyLayer,
S2Layer,
TerrainLayer,
Tile3DLayer,
TileLayer,
TripsLayer,
_WMSLayer as WMSLayer,
} from "@deck.gl/geo-layers";
import {
ArcLayer,
BitmapLayer,
ColumnLayer,
GeoJsonLayer,
GridCellLayer,
IconLayer,
LineLayer,
PathLayer,
PointCloudLayer,
PolygonLayer,
ScatterplotLayer,
SolidPolygonLayer,
TextLayer,
} from "@deck.gl/layers";
import { ScenegraphLayer, SimpleMeshLayer } from "@deck.gl/mesh-layers";
// Register all layers
extend({
// Views
MapView,
OrthographicView,
OrbitView,
FirstPersonView,
GlobeView,
// @deck.gl/layers
ArcLayer,
BitmapLayer,
IconLayer,
LineLayer,
PointCloudLayer,
ScatterplotLayer,
ColumnLayer,
GridCellLayer,
PathLayer,
PolygonLayer,
GeoJsonLayer,
TextLayer,
SolidPolygonLayer,
// @deck.gl/geo-layers
S2Layer,
QuadkeyLayer,
TileLayer,
TripsLayer,
H3ClusterLayer,
H3HexagonLayer,
Tile3DLayer,
TerrainLayer,
MVTLayer,
MvtLayer: MVTLayer,
WMSLayer,
WmsLayer: WMSLayer,
GeohashLayer,
GreatCircleLayer,
// @deck.gl/mesh-layers
ScenegraphLayer,
SimpleMeshLayer,
});
// Now v1 syntax works
<scatterplotLayer id="points" data={data} />;
最低限度登记 (只需要层):
// Register only what you use
import { extend } from "@deckgl-fiber-renderer/dom";
import { ScatterplotLayer, PathLayer } from "@deck.gl/layers";
extend({ ScatterplotLayer, PathLayer });
// Now these specific layers work
<scatterplotLayer id="points" data={data} />
<pathLayer id="routes" data={routes} />
下行停留在v1上:
- QQ 在开发模式中显示折旧警告
- QQ 将在 v3( 完全删除) 中断开
- QQ 不支持类型脚本通用
- 如果您使用完整的注册, 则将所有层都装入
- QQ 容易忘记注册层( 运行时间错误)
移徙清单
从 v1 移到 v2 :
-
删除副作用导入 (v2中的禁区):
// ❌ Remove this - doesn't work anymore import "@deckgl-fiber-renderer/reconciler/side-effects"; -
导入层构造器 :
// ✅ Add explicit imports import { ScatterplotLayer, PathLayer } from "@deck.gl/layers"; -
替换图层元素 :
// ❌ Old <scatterplotLayer id="points" data={data} getPosition={(d) => d.coordinates} /> // ✅ New <layer layer={new ScatterplotLayer({ id: "points", data, getPosition: (d) => d.coordinates })} /> -
删除
extend()电话 (不再需要) -
添加类型脚本通用 (可选但建议):
type DataPoint = { coordinates: [number, number]; value: number }; <layer layer={ new ScatterplotLayer<DataPoint>({ id: "points", data, getPosition: (d) => d.coordinates, // d typed as DataPoint }) } />;