为图层添加属性;新增水流动画图层的显示隐藏
This commit is contained in:
@@ -65,6 +65,12 @@ const DrawPanel: React.FC = () => {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
properties: {
|
||||||
|
name: "绘制图层", // 设置图层名称
|
||||||
|
value: "drawLayer",
|
||||||
|
type: "multigeometry",
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
map.addLayer(drawVectorLayer);
|
map.addLayer(drawVectorLayer);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Checkbox, FormControlLabel } from "@mui/material";
|
|||||||
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
|
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
|
||||||
import VectorLayer from "ol/layer/Vector";
|
import VectorLayer from "ol/layer/Vector";
|
||||||
import VectorTileLayer from "ol/layer/VectorTile";
|
import VectorTileLayer from "ol/layer/VectorTile";
|
||||||
|
import { DeckLayer } from "@utils/layers";
|
||||||
|
|
||||||
const LayerControl: React.FC = () => {
|
const LayerControl: React.FC = () => {
|
||||||
const map = useMap();
|
const map = useMap();
|
||||||
@@ -12,56 +13,126 @@ const LayerControl: React.FC = () => {
|
|||||||
const [layerVisibilities, setLayerVisibilities] = useState<
|
const [layerVisibilities, setLayerVisibilities] = useState<
|
||||||
Map<Layer, boolean>
|
Map<Layer, boolean>
|
||||||
>(new Map());
|
>(new Map());
|
||||||
|
const userChangedRef = React.useRef<Set<Layer>>(new Set());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
const mapLayers = map
|
|
||||||
.getLayers()
|
|
||||||
.getArray()
|
|
||||||
.filter(
|
|
||||||
(layer) =>
|
|
||||||
layer instanceof WebGLVectorTileLayer ||
|
|
||||||
layer instanceof VectorTileLayer ||
|
|
||||||
layer instanceof VectorLayer
|
|
||||||
) as Layer[];
|
|
||||||
|
|
||||||
// 定义图层排序顺序
|
const updateLayers = () => {
|
||||||
const layerOrder = [
|
const mapLayers = map
|
||||||
"junctions",
|
.getLayers()
|
||||||
"reservoirs",
|
.getArray()
|
||||||
"tanks",
|
.filter(
|
||||||
"pipes",
|
(layer) =>
|
||||||
"pumps",
|
layer instanceof WebGLVectorTileLayer ||
|
||||||
"valves",
|
layer instanceof VectorTileLayer ||
|
||||||
"scada",
|
layer instanceof VectorLayer
|
||||||
];
|
) as Layer[];
|
||||||
|
|
||||||
// 对图层进行排序
|
// 查找包含 waterflowLayer 的 DeckLayer
|
||||||
const sortedLayers = mapLayers.sort((a, b) => {
|
const deckFlowLayers = map
|
||||||
const nameA = a.get("value")?.toLowerCase() || "";
|
.getLayers()
|
||||||
const nameB = b.get("value")?.toLowerCase() || "";
|
.getArray()
|
||||||
const indexA = layerOrder.indexOf(nameA);
|
.filter((layer) => {
|
||||||
const indexB = layerOrder.indexOf(nameB);
|
if (layer instanceof DeckLayer) {
|
||||||
|
const deckLayers = layer.getDeckLayers();
|
||||||
|
// 检查是否包含 waterflowLayer
|
||||||
|
return deckLayers.some((dl: any) => dl.id === "waterflowLayer");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}) as Layer[];
|
||||||
|
|
||||||
// 如果图层不在排序列表中,放到最后
|
// 合并所有可控制的图层
|
||||||
if (indexA === -1 && indexB === -1) return 0;
|
const allLayers = [...mapLayers, ...deckFlowLayers];
|
||||||
if (indexA === -1) return 1;
|
|
||||||
if (indexB === -1) return -1;
|
|
||||||
|
|
||||||
return indexA - indexB;
|
// 定义图层排序顺序
|
||||||
});
|
const layerOrder = [
|
||||||
|
"junctions",
|
||||||
|
"reservoirs",
|
||||||
|
"tanks",
|
||||||
|
"pipes",
|
||||||
|
"pumps",
|
||||||
|
"valves",
|
||||||
|
"scada",
|
||||||
|
"waterflow",
|
||||||
|
];
|
||||||
|
|
||||||
setLayers(sortedLayers);
|
// 过滤并排序图层:只显示在 layerOrder 中的图层
|
||||||
const visible = new Map<Layer, boolean>();
|
const sortedLayers = allLayers
|
||||||
sortedLayers.forEach((layer) => {
|
.filter((layer) => {
|
||||||
visible.set(layer, layer.getVisible());
|
const value = layer.get("value")?.toLowerCase();
|
||||||
});
|
return layerOrder.includes(value);
|
||||||
setLayerVisibilities(visible);
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
const nameA = a.get("value")?.toLowerCase();
|
||||||
|
const nameB = b.get("value")?.toLowerCase();
|
||||||
|
const indexA = layerOrder.indexOf(nameA);
|
||||||
|
const indexB = layerOrder.indexOf(nameB);
|
||||||
|
|
||||||
|
return indexA - indexB;
|
||||||
|
});
|
||||||
|
|
||||||
|
setLayers(sortedLayers);
|
||||||
|
|
||||||
|
setLayerVisibilities((prevVisibilities) => {
|
||||||
|
const visible = new Map<Layer, boolean>();
|
||||||
|
sortedLayers.forEach((layer) => {
|
||||||
|
// 如果用户刚手动改变了这个图层,使用本地状态
|
||||||
|
if (userChangedRef.current.has(layer)) {
|
||||||
|
visible.set(layer, prevVisibilities.get(layer) ?? true);
|
||||||
|
} else if (layer instanceof DeckLayer) {
|
||||||
|
// 对于 DeckLayer,获取内部 deck.gl 图层的可见性
|
||||||
|
const waterflowVisible =
|
||||||
|
layer.getDeckLayerVisible("waterflowLayer");
|
||||||
|
visible.set(layer, waterflowVisible ?? true);
|
||||||
|
} else {
|
||||||
|
// 对于普通 OpenLayers 图层
|
||||||
|
visible.set(layer, layer.getVisible());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return visible;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始更新
|
||||||
|
updateLayers();
|
||||||
|
|
||||||
|
// 监听图层集合的变化
|
||||||
|
const layerCollection = map.getLayers();
|
||||||
|
layerCollection.on("change:length", updateLayers);
|
||||||
|
|
||||||
|
// 设置定时器定期检查 DeckLayer 内部图层的变化
|
||||||
|
const intervalId = setInterval(updateLayers, 500);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
layerCollection.un("change:length", updateLayers);
|
||||||
|
clearInterval(intervalId);
|
||||||
|
};
|
||||||
}, [map]);
|
}, [map]);
|
||||||
|
|
||||||
const handleVisibilityChange = (layer: Layer, visible: boolean) => {
|
const handleVisibilityChange = (layer: Layer, visible: boolean) => {
|
||||||
layer.setVisible(visible);
|
// 判断图层类型并调用相应的方法
|
||||||
|
if (layer instanceof DeckLayer) {
|
||||||
|
// 对于 DeckLayer,需要设置内部 deck.gl 图层的可见性
|
||||||
|
const deckLayers = layer.getDeckLayers();
|
||||||
|
deckLayers.forEach((deckLayer: any) => {
|
||||||
|
if (deckLayer && deckLayer.id === "waterflowLayer") {
|
||||||
|
layer.setDeckLayerVisible("waterflowLayer", visible);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 对于普通 OpenLayers 图层,使用 setVisible 方法
|
||||||
|
layer.setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记这个图层为用户手动改变
|
||||||
|
userChangedRef.current.add(layer);
|
||||||
setLayerVisibilities((prev) => new Map(prev).set(layer, visible));
|
setLayerVisibilities((prev) => new Map(prev).set(layer, visible));
|
||||||
|
|
||||||
|
// 1秒后移除标记,允许定时器更新
|
||||||
|
setTimeout(() => {
|
||||||
|
userChangedRef.current.delete(layer);
|
||||||
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -142,6 +142,12 @@ const Toolbar: React.FC<ToolbarProps> = ({ hiddenButtons, queryType }) => {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
properties: {
|
||||||
|
name: "属性查询高亮图层", // 设置图层名称
|
||||||
|
value: "info_highlight_layer",
|
||||||
|
type: "multigeometry",
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
map.addLayer(highLightLayer);
|
map.addLayer(highLightLayer);
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import View from "ol/View.js";
|
|||||||
import "ol/ol.css";
|
import "ol/ol.css";
|
||||||
import MapTools from "./MapTools";
|
import MapTools from "./MapTools";
|
||||||
|
|
||||||
import { Layer } from "ol/layer"; // 保留导入,但用于继承
|
// 导入 DeckLayer
|
||||||
|
import { DeckLayer } from "@utils/layers";
|
||||||
import VectorTileSource from "ol/source/VectorTile";
|
import VectorTileSource from "ol/source/VectorTile";
|
||||||
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
|
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
|
||||||
import MVT from "ol/format/MVT";
|
import MVT from "ol/format/MVT";
|
||||||
@@ -55,28 +56,6 @@ interface DataContextType {
|
|||||||
scadaData?: any[]; // SCADA 数据
|
scadaData?: any[]; // SCADA 数据
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建自定义Layer类来包装deck.gl
|
|
||||||
class DeckLayer extends Layer {
|
|
||||||
private deck: Deck;
|
|
||||||
|
|
||||||
constructor(deckInstance: Deck) {
|
|
||||||
super({});
|
|
||||||
this.deck = deckInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
render(frameState: any): HTMLElement {
|
|
||||||
const { size, viewState } = frameState;
|
|
||||||
const [width, height] = size;
|
|
||||||
const [longitude, latitude] = toLonLat(viewState.center);
|
|
||||||
const zoom = viewState.zoom - 1; // 调整 zoom 以匹配
|
|
||||||
const bearing = (-viewState.rotation * 180) / Math.PI;
|
|
||||||
const deckViewState = { bearing, longitude, latitude, zoom };
|
|
||||||
this.deck.setProps({ width, height, viewState: deckViewState });
|
|
||||||
this.deck.redraw();
|
|
||||||
// 返回deck.gl的canvas元素
|
|
||||||
return document.getElementById("deck-canvas") as HTMLElement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 跨组件传递
|
// 跨组件传递
|
||||||
const MapContext = createContext<OlMap | undefined>(undefined);
|
const MapContext = createContext<OlMap | undefined>(undefined);
|
||||||
const DataContext = createContext<DataContextType | undefined>(undefined);
|
const DataContext = createContext<DataContextType | undefined>(undefined);
|
||||||
@@ -107,6 +86,7 @@ export const useData = () => {
|
|||||||
const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||||
const mapRef = useRef<HTMLDivElement | null>(null);
|
const mapRef = useRef<HTMLDivElement | null>(null);
|
||||||
const deckRef = useRef<Deck | null>(null);
|
const deckRef = useRef<Deck | null>(null);
|
||||||
|
const deckFlowRef = useRef<Deck | null>(null);
|
||||||
|
|
||||||
const [map, setMap] = useState<OlMap>();
|
const [map, setMap] = useState<OlMap>();
|
||||||
// currentCalData 用于存储当前计算结果
|
// currentCalData 用于存储当前计算结果
|
||||||
@@ -134,6 +114,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
const [junctionText, setJunctionText] = useState("pressure");
|
const [junctionText, setJunctionText] = useState("pressure");
|
||||||
const [pipeText, setPipeText] = useState("flow");
|
const [pipeText, setPipeText] = useState("flow");
|
||||||
const flowAnimation = useRef(false); // 添加动画控制标志
|
const flowAnimation = useRef(false); // 添加动画控制标志
|
||||||
|
const waterflowUserVisible = useRef<boolean>(true); // 用户设置的水流图层可见性
|
||||||
const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别
|
const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别
|
||||||
|
|
||||||
// 防抖更新函数
|
// 防抖更新函数
|
||||||
@@ -648,6 +629,15 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
map.getView().on("change", handleViewChange);
|
map.getView().on("change", handleViewChange);
|
||||||
|
|
||||||
|
// 初始化当前缩放级别并强制触发瓦片加载
|
||||||
|
setTimeout(() => {
|
||||||
|
const initialZoom = map.getView().getZoom() || 11;
|
||||||
|
setCurrentZoom(initialZoom);
|
||||||
|
// 强制触发地图渲染,让瓦片加载事件触发
|
||||||
|
map.render();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// 初始化 deck.gl
|
// 初始化 deck.gl
|
||||||
const deck = new Deck({
|
const deck = new Deck({
|
||||||
initialViewState: {
|
initialViewState: {
|
||||||
@@ -664,6 +654,32 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
// deckLayer.setZIndex(1000); // 确保在最上层
|
// deckLayer.setZIndex(1000); // 确保在最上层
|
||||||
map.addLayer(deckLayer);
|
map.addLayer(deckLayer);
|
||||||
|
|
||||||
|
// 初始化水流动画的 deck.gl
|
||||||
|
const deckFlow = new Deck({
|
||||||
|
initialViewState: {
|
||||||
|
longitude: 0,
|
||||||
|
latitude: 0,
|
||||||
|
zoom: 1,
|
||||||
|
},
|
||||||
|
canvas: "deck-flow-canvas",
|
||||||
|
controller: false,
|
||||||
|
layers: [],
|
||||||
|
});
|
||||||
|
deckFlowRef.current = deckFlow;
|
||||||
|
const deckFlowLayer = new DeckLayer(deckFlow);
|
||||||
|
deckFlowLayer.set("name", "水流动画");
|
||||||
|
deckFlowLayer.set("value", "waterflow");
|
||||||
|
deckFlowLayer.set("type", "animation");
|
||||||
|
// 初始化用户可见性状态(默认为 true)
|
||||||
|
deckFlowLayer.initUserVisibility("waterflowLayer", true);
|
||||||
|
// 设置可见性变化回调,同步更新 waterflowUserVisible
|
||||||
|
deckFlowLayer.setVisibilityChangeCallback((layerId, visible) => {
|
||||||
|
if (layerId === "waterflowLayer") {
|
||||||
|
waterflowUserVisible.current = visible;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
map.addLayer(deckFlowLayer);
|
||||||
|
|
||||||
// 清理函数
|
// 清理函数
|
||||||
return () => {
|
return () => {
|
||||||
junctionsLayer.un("change:visible", handleJunctionVisibilityChange);
|
junctionsLayer.un("change:visible", handleJunctionVisibilityChange);
|
||||||
@@ -671,6 +687,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
map.setTarget(undefined);
|
map.setTarget(undefined);
|
||||||
map.dispose();
|
map.dispose();
|
||||||
deck.finalize();
|
deck.finalize();
|
||||||
|
deckFlow.finalize();
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -769,7 +786,10 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
getColor: [0, 220, 255],
|
getColor: [0, 220, 255],
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
visible:
|
visible:
|
||||||
flowAnimation.current && currentZoom >= 12 && currentZoom <= 24,
|
waterflowUserVisible.current &&
|
||||||
|
flowAnimation.current &&
|
||||||
|
currentZoom >= 12 &&
|
||||||
|
currentZoom <= 24,
|
||||||
widthMinPixels: 5,
|
widthMinPixels: 5,
|
||||||
jointRounded: true, // 拐角变圆
|
jointRounded: true, // 拐角变圆
|
||||||
// capRounded: true, // 端点变圆
|
// capRounded: true, // 端点变圆
|
||||||
@@ -810,6 +830,75 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
flowAnimation.current = false;
|
flowAnimation.current = false;
|
||||||
}
|
}
|
||||||
}, [currentPipeCalData, pipeText]);
|
}, [currentPipeCalData, pipeText]);
|
||||||
|
|
||||||
|
// 水流动画循环
|
||||||
|
useEffect(() => {
|
||||||
|
const deckFlow = deckFlowRef.current;
|
||||||
|
if (!deckFlow || !flowAnimation.current || pipeData.length === 0) {
|
||||||
|
// 如果不需要动画,清空图层
|
||||||
|
if (deckFlow) {
|
||||||
|
deckFlow.setProps({ layers: [] });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let animationId: number;
|
||||||
|
const animate = () => {
|
||||||
|
if (!deckFlow || !flowAnimation.current) return;
|
||||||
|
if (pipeData.length === 0) {
|
||||||
|
animationId = requestAnimationFrame(animate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动画总时长(秒)
|
||||||
|
const animationDuration = 10;
|
||||||
|
// 缓冲时间(秒)
|
||||||
|
const bufferTime = 2;
|
||||||
|
// 完整循环周期
|
||||||
|
const loopLength = animationDuration + bufferTime;
|
||||||
|
// 确保时间范围与你的时间戳数据匹配
|
||||||
|
const currentTime = (Date.now() / 1000) % loopLength; // (0,12) 之间循环
|
||||||
|
|
||||||
|
const waterflowLayer = new TripsLayer({
|
||||||
|
id: "waterflowLayer",
|
||||||
|
data: pipeData,
|
||||||
|
getPath: (d) => d.path,
|
||||||
|
getTimestamps: (d) => {
|
||||||
|
return d.timestamps; // 这些应该是与 currentTime 匹配的数值
|
||||||
|
},
|
||||||
|
getColor: [0, 220, 255],
|
||||||
|
opacity: 0.8,
|
||||||
|
visible:
|
||||||
|
waterflowUserVisible.current &&
|
||||||
|
flowAnimation.current &&
|
||||||
|
currentZoom >= 12 &&
|
||||||
|
currentZoom <= 24,
|
||||||
|
widthMinPixels: 5,
|
||||||
|
jointRounded: true, // 拐角变圆
|
||||||
|
// capRounded: true, // 端点变圆
|
||||||
|
trailLength: 2, // 水流尾迹淡出时间
|
||||||
|
currentTime: currentTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
deckFlow.setProps({
|
||||||
|
layers: [waterflowLayer],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 继续请求动画帧,每帧执行一次函数
|
||||||
|
animationId = requestAnimationFrame(animate);
|
||||||
|
};
|
||||||
|
animate();
|
||||||
|
|
||||||
|
// 清理函数
|
||||||
|
return () => {
|
||||||
|
if (animationId) {
|
||||||
|
cancelAnimationFrame(animationId);
|
||||||
|
}
|
||||||
|
if (deckFlow) {
|
||||||
|
deckFlow.setProps({ layers: [] });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [flowAnimation, pipeData, currentZoom]);
|
||||||
// 计算值更新时,更新 junctionData 和 pipeData
|
// 计算值更新时,更新 junctionData 和 pipeData
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const junctionProperties = junctionText;
|
const junctionProperties = junctionText;
|
||||||
@@ -890,6 +979,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
<canvas id="deck-canvas" />
|
<canvas id="deck-canvas" />
|
||||||
|
<canvas id="deck-flow-canvas" />
|
||||||
</MapContext.Provider>
|
</MapContext.Provider>
|
||||||
</DataContext.Provider>
|
</DataContext.Provider>
|
||||||
</>
|
</>
|
||||||
|
|||||||
121
src/utils/layers.ts
Normal file
121
src/utils/layers.ts
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import { Layer } from "ol/layer";
|
||||||
|
import { Deck } from "@deck.gl/core";
|
||||||
|
import { toLonLat } from "ol/proj";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 Layer 类来包装 deck.gl
|
||||||
|
* 将 deck.gl 图层集成到 OpenLayers 地图中
|
||||||
|
*/
|
||||||
|
export class DeckLayer extends Layer {
|
||||||
|
private deck: Deck;
|
||||||
|
private onVisibilityChange?: (layerId: string, visible: boolean) => void;
|
||||||
|
private userVisibility: Map<string, boolean> = new Map(); // 存储用户设置的可见性
|
||||||
|
|
||||||
|
constructor(deckInstance: Deck) {
|
||||||
|
super({});
|
||||||
|
this.deck = deckInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置可见性变化回调
|
||||||
|
setVisibilityChangeCallback(
|
||||||
|
callback: (layerId: string, visible: boolean) => void
|
||||||
|
): void {
|
||||||
|
this.onVisibilityChange = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化用户可见性状态
|
||||||
|
initUserVisibility(layerId: string, visible: boolean): void {
|
||||||
|
this.userVisibility.set(layerId, visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(frameState: any): HTMLElement {
|
||||||
|
const { size, viewState } = frameState;
|
||||||
|
const [width, height] = size;
|
||||||
|
const [longitude, latitude] = toLonLat(viewState.center);
|
||||||
|
const zoom = viewState.zoom - 1; // 调整 zoom 以匹配
|
||||||
|
const bearing = (-viewState.rotation * 180) / Math.PI;
|
||||||
|
const deckViewState = { bearing, longitude, latitude, zoom };
|
||||||
|
this.deck.setProps({ width, height, viewState: deckViewState });
|
||||||
|
this.deck.redraw();
|
||||||
|
return document.getElementById("deck-canvas") as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 Deck 实例
|
||||||
|
getDeck(): Deck {
|
||||||
|
return this.deck;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置图层
|
||||||
|
setDeckLayers(layers: any[]): void {
|
||||||
|
this.deck.setProps({ layers });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前图层
|
||||||
|
getDeckLayers(): any[] {
|
||||||
|
return this.deck.props.layers || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加图层
|
||||||
|
addDeckLayer(layer: any): void {
|
||||||
|
const currentLayers = this.getDeckLayers();
|
||||||
|
this.deck.setProps({ layers: [...currentLayers, layer] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除图层
|
||||||
|
removeDeckLayer(layerId: string): void {
|
||||||
|
const currentLayers = this.getDeckLayers();
|
||||||
|
const filteredLayers = currentLayers.filter(
|
||||||
|
(layer: any) => layer && layer.id !== layerId
|
||||||
|
);
|
||||||
|
this.deck.setProps({ layers: filteredLayers });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据 ID 查找图层
|
||||||
|
getDeckLayerById(layerId: string): any | undefined {
|
||||||
|
const layers = this.getDeckLayers();
|
||||||
|
return layers.find((layer: any) => layer && layer.id === layerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新特定图层
|
||||||
|
updateDeckLayer(layerId: string, props: any): void {
|
||||||
|
const layers = this.getDeckLayers();
|
||||||
|
const updatedLayers = layers.map((layer: any) => {
|
||||||
|
if (layer && layer.id === layerId) {
|
||||||
|
return layer.clone(props);
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
});
|
||||||
|
this.deck.setProps({ layers: updatedLayers });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取图层的可见性(用户设置的状态,不受其他条件影响)
|
||||||
|
getDeckLayerVisible(layerId: string): boolean | undefined {
|
||||||
|
// 优先返回用户设置的可见性
|
||||||
|
if (this.userVisibility.has(layerId)) {
|
||||||
|
return this.userVisibility.get(layerId);
|
||||||
|
}
|
||||||
|
// 如果没有用户设置,返回实际图层的可见性
|
||||||
|
const layer = this.getDeckLayerById(layerId);
|
||||||
|
return layer ? layer.props.visible : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置图层的可见性
|
||||||
|
setDeckLayerVisible(layerId: string, visible: boolean): void {
|
||||||
|
// 存储用户设置的可见性
|
||||||
|
this.userVisibility.set(layerId, visible);
|
||||||
|
// 更新图层(注意:实际的 visible 可能还受其他条件控制)
|
||||||
|
this.updateDeckLayer(layerId, { visible });
|
||||||
|
// 触发回调通知外部
|
||||||
|
if (this.onVisibilityChange) {
|
||||||
|
this.onVisibilityChange(layerId, visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换图层的可见性
|
||||||
|
toggleDeckLayerVisible(layerId: string): void {
|
||||||
|
const currentVisible = this.getDeckLayerVisible(layerId);
|
||||||
|
if (currentVisible !== undefined) {
|
||||||
|
this.setDeckLayerVisible(layerId, !currentVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user