完善时间轴数据更新函数;完善图层显示控制函数;修复图例样式显示异常问题;
This commit is contained in:
@@ -24,15 +24,18 @@ import { bearing } from "@turf/turf";
|
||||
import { Deck } from "@deck.gl/core";
|
||||
import { TextLayer } from "@deck.gl/layers";
|
||||
import { TripsLayer } from "@deck.gl/geo-layers";
|
||||
import { el, tr } from "date-fns/locale";
|
||||
import RenderFeature from "ol/render/Feature";
|
||||
import { set } from "date-fns";
|
||||
|
||||
interface MapComponentProps {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
interface DataContextType {
|
||||
junctionData: any[];
|
||||
pipeData: any[];
|
||||
setJunctionDataState: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
setPipeDataState: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
currentJunctionCalData?: any[]; // 当前计算结果
|
||||
setCurrentJunctionCalData?: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
currentPipeCalData?: any[]; // 当前计算结果
|
||||
setCurrentPipeCalData?: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
showJunctionText?: boolean; // 是否显示节点文本
|
||||
showPipeText?: boolean; // 是否显示管道文本
|
||||
setShowJunctionText?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
@@ -96,6 +99,12 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
const deckRef = useRef<Deck | null>(null);
|
||||
|
||||
const [map, setMap] = useState<OlMap>();
|
||||
// currentCalData 用于存储当前计算结果
|
||||
const [currentJunctionCalData, setCurrentJunctionCalData] = useState<any[]>(
|
||||
[]
|
||||
);
|
||||
const [currentPipeCalData, setCurrentPipeCalData] = useState<any[]>([]);
|
||||
// junctionData 和 pipeData 分别缓存瓦片解析后节点和管道的数据,用于 deck.gl 定位、标签渲染
|
||||
const [junctionData, setJunctionDataState] = useState<any[]>([]);
|
||||
const [pipeData, setPipeDataState] = useState<any[]>([]);
|
||||
const junctionDataIds = useRef(new Set<string>());
|
||||
@@ -105,9 +114,11 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
|
||||
const [showJunctionText, setShowJunctionText] = useState(false); // 控制节点文本显示
|
||||
const [showPipeText, setShowPipeText] = useState(false); // 控制管道文本显示
|
||||
const [junctionText, setJunctionText] = useState("");
|
||||
const [pipeText, setPipeText] = useState("");
|
||||
const flowAnimation = useRef(true); // 添加动画控制标志
|
||||
const [showJunctionTextLayer, setShowJunctionTextLayer] = useState(true); // 控制节点文本图层显示
|
||||
const [showPipeTextLayer, setShowPipeTextLayer] = useState(true); // 控制管道文本图层显示
|
||||
const [junctionText, setJunctionText] = useState("pressure");
|
||||
const [pipeText, setPipeText] = useState("flow");
|
||||
const flowAnimation = useRef(false); // 添加动画控制标志
|
||||
const [currentZoom, setCurrentZoom] = useState(12); // 当前缩放级别
|
||||
// 防抖更新函数
|
||||
const debouncedUpdateData = useRef(
|
||||
@@ -149,37 +160,82 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
setPipeDataState((prev) => [...prev, ...uniqueNewData]);
|
||||
}
|
||||
};
|
||||
const defaultFlatStyle: FlatStyleLike = {
|
||||
"stroke-width": 3,
|
||||
"stroke-color": "rgba(51, 153, 204, 0.9)",
|
||||
"circle-fill-color": "rgba(255,255,255,0.4)",
|
||||
"circle-stroke-color": "rgba(255,255,255,0.9)",
|
||||
"circle-radius": [
|
||||
"interpolate",
|
||||
["linear"],
|
||||
["zoom"],
|
||||
12,
|
||||
1, // 在缩放级别 12 时,圆形半径为 1px
|
||||
24,
|
||||
12, // 在缩放级别 24 时,圆形半径为 12px
|
||||
],
|
||||
};
|
||||
// 矢量瓦片数据源和图层
|
||||
const junctionSource = new VectorTileSource({
|
||||
url: `${mapUrl}/gwc/service/tms/1.0.0/TJWater:geo_junctions_mat@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||
format: new MVT(),
|
||||
projection: "EPSG:3857",
|
||||
});
|
||||
const pipeSource = new VectorTileSource({
|
||||
url: `${mapUrl}/gwc/service/tms/1.0.0/TJWater:geo_pipes_mat@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||
format: new MVT(),
|
||||
projection: "EPSG:3857",
|
||||
});
|
||||
// WebGL 渲染优化显示
|
||||
const junctionLayer = new WebGLVectorTileLayer({
|
||||
source: junctionSource as any, // 使用 WebGL 渲染
|
||||
style: defaultFlatStyle,
|
||||
extent: extent, // 设置图层范围
|
||||
maxZoom: 24,
|
||||
minZoom: 12,
|
||||
properties: {
|
||||
name: "节点图层", // 设置图层名称
|
||||
value: "junctions",
|
||||
type: "point",
|
||||
properties: [
|
||||
// { name: "需求量", value: "demand" },
|
||||
// { name: "海拔高度", value: "elevation" },
|
||||
{ name: "实际需求量", value: "actualdemand" },
|
||||
{ name: "水头", value: "head" },
|
||||
{ name: "压力", value: "pressure" },
|
||||
{ name: "水质", value: "quality" },
|
||||
],
|
||||
},
|
||||
});
|
||||
const pipeLayer = new WebGLVectorTileLayer({
|
||||
source: pipeSource as any, // 使用 WebGL 渲染
|
||||
style: defaultFlatStyle,
|
||||
extent: extent, // 设置图层范围
|
||||
maxZoom: 24,
|
||||
minZoom: 12,
|
||||
properties: {
|
||||
name: "管道图层", // 设置图层名称
|
||||
value: "pipes",
|
||||
type: "linestring",
|
||||
properties: [
|
||||
// { name: "直径", value: "diameter" },
|
||||
// { name: "粗糙度", value: "roughness" },
|
||||
// { name: "局部损失", value: "minor_loss" },
|
||||
{ name: "流量", value: "flow" },
|
||||
{ name: "摩阻系数", value: "friction" },
|
||||
{ name: "水头损失", value: "headloss" },
|
||||
{ name: "水质", value: "quality" },
|
||||
{ name: "反应速率", value: "reaction" },
|
||||
{ name: "设置值", value: "setting" },
|
||||
{ name: "状态", value: "status" },
|
||||
{ name: "流速", value: "velocity" },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!mapRef.current) return;
|
||||
// 添加 MVT 瓦片加载逻辑
|
||||
const defaultFlatStyle: FlatStyleLike = {
|
||||
"stroke-width": 3,
|
||||
"stroke-color": "rgba(51, 153, 204, 0.9)",
|
||||
"circle-fill-color": "rgba(255,255,255,0.4)",
|
||||
"circle-stroke-color": "rgba(255,255,255,0.9)",
|
||||
"circle-radius": [
|
||||
"interpolate",
|
||||
["linear"],
|
||||
["zoom"],
|
||||
12,
|
||||
1, // 在缩放级别 12 时,圆形半径为 1px
|
||||
24,
|
||||
12, // 在缩放级别 24 时,圆形半径为 12px
|
||||
],
|
||||
};
|
||||
const junctionSource = new VectorTileSource({
|
||||
url: `${mapUrl}/gwc/service/tms/1.0.0/TJWater:geo_junctions_mat@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||
format: new MVT(),
|
||||
projection: "EPSG:3857",
|
||||
});
|
||||
const pipeSource = new VectorTileSource({
|
||||
url: `${mapUrl}/gwc/service/tms/1.0.0/TJWater:geo_pipes_mat@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||
format: new MVT(),
|
||||
projection: "EPSG:3857",
|
||||
});
|
||||
|
||||
// 缓存数据
|
||||
// 缓存 junction、pipe 数据,提供给 deck.gl 显示标签使用
|
||||
junctionSource.on("tileloadend", (event) => {
|
||||
try {
|
||||
if (event.tile instanceof VectorTile) {
|
||||
@@ -290,54 +346,20 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
console.error("Pipe tile load error:", error);
|
||||
}
|
||||
});
|
||||
|
||||
// WebGL 渲染优化显示
|
||||
const junctionLayer = new WebGLVectorTileLayer({
|
||||
source: junctionSource as any, // 使用 WebGL 渲染
|
||||
style: defaultFlatStyle,
|
||||
extent: extent, // 设置图层范围
|
||||
maxZoom: 24,
|
||||
minZoom: 12,
|
||||
properties: {
|
||||
name: "节点图层", // 设置图层名称
|
||||
value: "junctions",
|
||||
type: "point",
|
||||
properties: [
|
||||
// { name: "需求量", value: "demand" },
|
||||
// { name: "海拔高度", value: "elevation" },
|
||||
{ name: "实际需求量", value: "actualdemand" },
|
||||
{ name: "水头", value: "head" },
|
||||
{ name: "压力", value: "pressure" },
|
||||
{ name: "水质", value: "quality" },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const pipeLayer = new WebGLVectorTileLayer({
|
||||
source: pipeSource as any, // 使用 WebGL 渲染
|
||||
style: defaultFlatStyle,
|
||||
extent: extent, // 设置图层范围
|
||||
maxZoom: 24,
|
||||
minZoom: 12,
|
||||
properties: {
|
||||
name: "管道图层", // 设置图层名称
|
||||
value: "pipes",
|
||||
type: "linestring",
|
||||
properties: [
|
||||
// { name: "直径", value: "diameter" },
|
||||
// { name: "粗糙度", value: "roughness" },
|
||||
// { name: "局部损失", value: "minor_loss" },
|
||||
{ name: "流量", value: "flow" },
|
||||
{ name: "摩阻系数", value: "friction" },
|
||||
{ name: "水头损失", value: "headloss" },
|
||||
{ name: "水质", value: "quality" },
|
||||
{ name: "反应速率", value: "reaction" },
|
||||
{ name: "设置值", value: "setting" },
|
||||
{ name: "状态", value: "status" },
|
||||
{ name: "流速", value: "velocity" },
|
||||
],
|
||||
},
|
||||
});
|
||||
// 更新标签可见性状态
|
||||
// 监听 junctionLayer 的 visible 变化
|
||||
const handleJunctionVisibilityChange = () => {
|
||||
const isVisible = junctionLayer.getVisible();
|
||||
setShowJunctionTextLayer(isVisible);
|
||||
};
|
||||
// 监听 pipeLayer 的 visible 变化
|
||||
const handlePipeVisibilityChange = () => {
|
||||
const isVisible = pipeLayer.getVisible();
|
||||
setShowPipeTextLayer(isVisible);
|
||||
};
|
||||
// 添加事件监听器
|
||||
junctionLayer.on("change:visible", handleJunctionVisibilityChange);
|
||||
pipeLayer.on("change:visible", handlePipeVisibilityChange);
|
||||
|
||||
const map = new OlMap({
|
||||
target: mapRef.current,
|
||||
@@ -375,8 +397,11 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
const deckLayer = new DeckLayer(deck);
|
||||
// deckLayer.setZIndex(1000); // 确保在最上层
|
||||
map.addLayer(deckLayer);
|
||||
|
||||
// 清理函数
|
||||
return () => {
|
||||
junctionLayer.un("change:visible", handleJunctionVisibilityChange);
|
||||
pipeLayer.un("change:visible", handlePipeVisibilityChange);
|
||||
map.setTarget(undefined);
|
||||
map.dispose();
|
||||
deck.finalize();
|
||||
@@ -402,7 +427,8 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
getTextAnchor: "middle",
|
||||
getAlignmentBaseline: "center",
|
||||
getPixelOffset: [0, -10],
|
||||
visible: currentZoom >= 15 && currentZoom <= 24,
|
||||
visible:
|
||||
showJunctionTextLayer && currentZoom >= 15 && currentZoom <= 24,
|
||||
// --- 修改以下属性 ---
|
||||
// characterSet: "auto",
|
||||
// outlineWidth: 4,
|
||||
@@ -422,7 +448,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
getPixelOffset: [0, -8],
|
||||
getTextAnchor: "middle",
|
||||
getAlignmentBaseline: "bottom",
|
||||
visible: currentZoom >= 15 && currentZoom <= 24,
|
||||
visible: showPipeTextLayer && currentZoom >= 15 && currentZoom <= 24,
|
||||
// --- 修改以下属性 ---
|
||||
// characterSet: "auto",
|
||||
// outlineWidth: 5,
|
||||
@@ -456,6 +482,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
},
|
||||
getColor: [0, 220, 255],
|
||||
opacity: 0.8,
|
||||
visible: currentZoom >= 12 && currentZoom <= 24,
|
||||
widthMinPixels: 5,
|
||||
jointRounded: true, // 拐角变圆
|
||||
// capRounded: true, // 端点变圆
|
||||
@@ -476,16 +503,85 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
requestAnimationFrame(animate);
|
||||
};
|
||||
animate();
|
||||
}, [flowAnimation, junctionData, pipeData]);
|
||||
}, [
|
||||
flowAnimation,
|
||||
junctionData,
|
||||
pipeData,
|
||||
currentZoom,
|
||||
showJunctionText,
|
||||
showPipeText,
|
||||
showJunctionTextLayer,
|
||||
showPipeTextLayer,
|
||||
junctionText,
|
||||
pipeText,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (pipeText === "flow") {
|
||||
flowAnimation.current = true;
|
||||
} else {
|
||||
flowAnimation.current = false;
|
||||
}
|
||||
}, [pipeText]);
|
||||
// 计算值更新时,更新 junctionData 和 pipeData
|
||||
useEffect(() => {
|
||||
const junctionProperties = junctionText;
|
||||
const pipeProperties = pipeText;
|
||||
|
||||
// 将 nodeRecords 转换为 Map 以提高查找效率
|
||||
const nodeMap: Map<string, any> = new Map(
|
||||
currentJunctionCalData.map((r: any) => [r.ID, r])
|
||||
);
|
||||
// 将 linkRecords 转换为 Map 以提高查找效率
|
||||
const linkMap: Map<string, any> = new Map(
|
||||
currentPipeCalData.map((r: any) => [r.ID, r])
|
||||
);
|
||||
|
||||
// 更新junctionData
|
||||
setJunctionDataState((prev: any[]) =>
|
||||
prev.map((j) => {
|
||||
const record = nodeMap.get(j.id);
|
||||
if (record) {
|
||||
return {
|
||||
...j,
|
||||
[junctionProperties]: record.value,
|
||||
};
|
||||
}
|
||||
return j;
|
||||
})
|
||||
);
|
||||
|
||||
// 更新pipeData
|
||||
setPipeDataState((prev: any[]) =>
|
||||
prev.map((p) => {
|
||||
const record = linkMap.get(p.id);
|
||||
if (record) {
|
||||
return {
|
||||
...p,
|
||||
flowFlag: pipeProperties === "flow" && record.value < 0 ? -1 : 1,
|
||||
path:
|
||||
pipeProperties === "flow" && record.value < 0 && p.flowFlag > 0
|
||||
? [...p.path].reverse()
|
||||
: p.path,
|
||||
[pipeProperties]: record.value,
|
||||
};
|
||||
}
|
||||
return p;
|
||||
})
|
||||
);
|
||||
}, [currentJunctionCalData, currentPipeCalData]);
|
||||
return (
|
||||
<>
|
||||
<DataContext.Provider
|
||||
value={{
|
||||
junctionData,
|
||||
pipeData,
|
||||
setJunctionDataState,
|
||||
setPipeDataState,
|
||||
currentJunctionCalData,
|
||||
setCurrentJunctionCalData,
|
||||
currentPipeCalData,
|
||||
setCurrentPipeCalData,
|
||||
setShowJunctionText,
|
||||
setShowPipeText,
|
||||
setJunctionText,
|
||||
setPipeText,
|
||||
showJunctionText,
|
||||
showPipeText,
|
||||
junctionText,
|
||||
|
||||
Reference in New Issue
Block a user