去掉全局 id="deck-canvas" 路径,改为实例级 canvasRef,修复可能出现的 Uncaught Error: deck.gl: assertion failed 的问题
This commit is contained in:
+47
-3
@@ -8,6 +8,8 @@ import { toLonLat } from "ol/proj";
|
||||
*/
|
||||
export class DeckLayer extends Layer {
|
||||
private deck: Deck;
|
||||
private canvasEl: HTMLCanvasElement | null;
|
||||
private isDisposed = false;
|
||||
private onVisibilityChange?: (layerId: string, visible: boolean) => void;
|
||||
private userVisibility: Map<string, boolean> = new Map(); // 存储用户设置的可见性
|
||||
|
||||
@@ -15,10 +17,15 @@ export class DeckLayer extends Layer {
|
||||
* @param deckInstance deck.gl 实例
|
||||
* @param layerProperties 可选:在构造时直接设置到 OpenLayers Layer 的 properties
|
||||
*/
|
||||
constructor(deckInstance: Deck, layerProperties?: Record<string, any>) {
|
||||
constructor(
|
||||
deckInstance: Deck,
|
||||
canvasElement: HTMLCanvasElement | null,
|
||||
layerProperties?: Record<string, any>
|
||||
) {
|
||||
// 将 layerProperties 作为 Layer 的 properties 传入
|
||||
super({ properties: layerProperties || {} });
|
||||
this.deck = deckInstance;
|
||||
this.canvasEl = canvasElement;
|
||||
// 再次确保属性应用到实例(兼容场景)
|
||||
if (layerProperties) {
|
||||
this.setProperties(layerProperties);
|
||||
@@ -38,6 +45,9 @@ export class DeckLayer extends Layer {
|
||||
}
|
||||
|
||||
render(frameState: any): HTMLElement {
|
||||
if (this.isDisposed) {
|
||||
return this.canvasEl || document.createElement("div");
|
||||
}
|
||||
const { size, viewState } = frameState;
|
||||
const [width, height] = size;
|
||||
const [longitude, latitude] = toLonLat(viewState.center);
|
||||
@@ -46,7 +56,7 @@ export class DeckLayer extends Layer {
|
||||
const deckViewState = { bearing, longitude, latitude, zoom };
|
||||
this.deck.setProps({ width, height, viewState: deckViewState });
|
||||
this.deck.redraw();
|
||||
return document.getElementById("deck-canvas") as HTMLElement;
|
||||
return this.canvasEl || document.createElement("div");
|
||||
}
|
||||
|
||||
// 获取 Deck 实例
|
||||
@@ -56,16 +66,19 @@ export class DeckLayer extends Layer {
|
||||
|
||||
// 设置图层
|
||||
setDeckLayers(layers: any[]): void {
|
||||
if (this.isDisposed) return;
|
||||
this.deck.setProps({ layers });
|
||||
}
|
||||
|
||||
// 获取当前图层
|
||||
getDeckLayers(): any[] {
|
||||
if (this.isDisposed) return [];
|
||||
return this.deck.props.layers || [];
|
||||
}
|
||||
|
||||
// 添加图层
|
||||
addDeckLayer(layer: any): void {
|
||||
if (this.isDisposed) return;
|
||||
const currentLayers = this.getDeckLayers();
|
||||
// 如果已有同 id 图层,则替换保持顺序;否则追加
|
||||
const idx = currentLayers.findIndex((l: any) => l && l.id === layer.id);
|
||||
@@ -80,6 +93,7 @@ export class DeckLayer extends Layer {
|
||||
|
||||
// 移除图层
|
||||
removeDeckLayer(layerId: string): void {
|
||||
if (this.isDisposed) return;
|
||||
const currentLayers = this.getDeckLayers();
|
||||
const filteredLayers = currentLayers.filter(
|
||||
(layer: any) => layer && layer.id !== layerId
|
||||
@@ -97,6 +111,7 @@ export class DeckLayer extends Layer {
|
||||
// - 如果传入的是 Layer 实例,则直接替换同 id 的图层为该实例
|
||||
// - 如果传入的是 props(普通对象),则基于原图层调用 clone(props)
|
||||
updateDeckLayer(layerId: string, layerOrProps: any): void {
|
||||
if (this.isDisposed) return;
|
||||
const layers = this.getDeckLayers();
|
||||
const updatedLayers = layers.map((layer: any) => {
|
||||
if (!layer || layer.id !== layerId) return layer;
|
||||
@@ -111,6 +126,13 @@ export class DeckLayer extends Layer {
|
||||
// 替换为新的 layer 实例
|
||||
return layerOrProps;
|
||||
}
|
||||
|
||||
if (layerOrProps && typeof layer.clone === "function") {
|
||||
// 传入 props 时,基于原图层 clone,避免丢失类型
|
||||
return layer.clone(layerOrProps);
|
||||
}
|
||||
|
||||
return layer;
|
||||
});
|
||||
|
||||
this.deck.setProps({ layers: updatedLayers });
|
||||
@@ -137,7 +159,7 @@ export class DeckLayer extends Layer {
|
||||
if (!found) return;
|
||||
try {
|
||||
// 使用 clone 来确保保持同类型实例
|
||||
this.updateDeckLayer(layerId, { ...found.props, visible });
|
||||
this.updateDeckLayer(layerId, { visible });
|
||||
} catch (err) {
|
||||
// 降级:直接替换属性
|
||||
this.updateDeckLayer(layerId, { visible });
|
||||
@@ -160,4 +182,26 @@ export class DeckLayer extends Layer {
|
||||
setLayerProperties(props: Record<string, any>): void {
|
||||
this.setProperties(props);
|
||||
}
|
||||
|
||||
isDisposedLayer(): boolean {
|
||||
return this.isDisposed;
|
||||
}
|
||||
|
||||
disposeDeck(): void {
|
||||
if (this.isDisposed) return;
|
||||
this.isDisposed = true;
|
||||
this.onVisibilityChange = undefined;
|
||||
this.userVisibility.clear();
|
||||
try {
|
||||
this.deck.setProps({ layers: [] });
|
||||
} catch (error) {
|
||||
console.warn("Clear deck layers failed", error);
|
||||
}
|
||||
try {
|
||||
this.deck.finalize();
|
||||
} catch (error) {
|
||||
console.warn("Finalize deck failed", error);
|
||||
}
|
||||
this.canvasEl = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user