为图层添加属性;新增水流动画图层的显示隐藏
This commit is contained in:
@@ -12,7 +12,8 @@ import View from "ol/View.js";
|
||||
import "ol/ol.css";
|
||||
import MapTools from "./MapTools";
|
||||
|
||||
import { Layer } from "ol/layer"; // 保留导入,但用于继承
|
||||
// 导入 DeckLayer
|
||||
import { DeckLayer } from "@utils/layers";
|
||||
import VectorTileSource from "ol/source/VectorTile";
|
||||
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
|
||||
import MVT from "ol/format/MVT";
|
||||
@@ -55,28 +56,6 @@ interface DataContextType {
|
||||
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 DataContext = createContext<DataContextType | undefined>(undefined);
|
||||
@@ -107,6 +86,7 @@ export const useData = () => {
|
||||
const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
const mapRef = useRef<HTMLDivElement | null>(null);
|
||||
const deckRef = useRef<Deck | null>(null);
|
||||
const deckFlowRef = useRef<Deck | null>(null);
|
||||
|
||||
const [map, setMap] = useState<OlMap>();
|
||||
// currentCalData 用于存储当前计算结果
|
||||
@@ -134,6 +114,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
const [junctionText, setJunctionText] = useState("pressure");
|
||||
const [pipeText, setPipeText] = useState("flow");
|
||||
const flowAnimation = useRef(false); // 添加动画控制标志
|
||||
const waterflowUserVisible = useRef<boolean>(true); // 用户设置的水流图层可见性
|
||||
const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别
|
||||
|
||||
// 防抖更新函数
|
||||
@@ -648,6 +629,15 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
}, 0);
|
||||
};
|
||||
map.getView().on("change", handleViewChange);
|
||||
|
||||
// 初始化当前缩放级别并强制触发瓦片加载
|
||||
setTimeout(() => {
|
||||
const initialZoom = map.getView().getZoom() || 11;
|
||||
setCurrentZoom(initialZoom);
|
||||
// 强制触发地图渲染,让瓦片加载事件触发
|
||||
map.render();
|
||||
}, 100);
|
||||
|
||||
// 初始化 deck.gl
|
||||
const deck = new Deck({
|
||||
initialViewState: {
|
||||
@@ -664,6 +654,32 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
// deckLayer.setZIndex(1000); // 确保在最上层
|
||||
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 () => {
|
||||
junctionsLayer.un("change:visible", handleJunctionVisibilityChange);
|
||||
@@ -671,6 +687,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
map.setTarget(undefined);
|
||||
map.dispose();
|
||||
deck.finalize();
|
||||
deckFlow.finalize();
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -769,7 +786,10 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
getColor: [0, 220, 255],
|
||||
opacity: 0.8,
|
||||
visible:
|
||||
flowAnimation.current && currentZoom >= 12 && currentZoom <= 24,
|
||||
waterflowUserVisible.current &&
|
||||
flowAnimation.current &&
|
||||
currentZoom >= 12 &&
|
||||
currentZoom <= 24,
|
||||
widthMinPixels: 5,
|
||||
jointRounded: true, // 拐角变圆
|
||||
// capRounded: true, // 端点变圆
|
||||
@@ -810,6 +830,75 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
flowAnimation.current = false;
|
||||
}
|
||||
}, [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
|
||||
useEffect(() => {
|
||||
const junctionProperties = junctionText;
|
||||
@@ -890,6 +979,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
{children}
|
||||
</div>
|
||||
<canvas id="deck-canvas" />
|
||||
<canvas id="deck-flow-canvas" />
|
||||
</MapContext.Provider>
|
||||
</DataContext.Provider>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user