完成节点样式变更
This commit is contained in:
@@ -17,11 +17,10 @@ import {
|
|||||||
ChevronRight,
|
ChevronRight,
|
||||||
FormatListBulleted,
|
FormatListBulleted,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style";
|
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
|
||||||
import VectorLayer from "ol/layer/Vector";
|
import VectorTileSource from "ol/source/VectorTile";
|
||||||
import VectorSource from "ol/source/Vector";
|
import { VectorTile } from "ol";
|
||||||
import Feature from "ol/Feature";
|
import { FlatStyleLike } from "ol/style/flat";
|
||||||
import { queryFeaturesByIds } from "@/utils/mapQueryService";
|
|
||||||
import { useMap } from "@app/OlMap/MapComponent";
|
import { useMap } from "@app/OlMap/MapComponent";
|
||||||
import StyleLegend from "@app/OlMap/Controls/StyleLegend";
|
import StyleLegend from "@app/OlMap/Controls/StyleLegend";
|
||||||
import AnalysisParameters from "./AnalysisParameters";
|
import AnalysisParameters from "./AnalysisParameters";
|
||||||
@@ -29,6 +28,7 @@ import SchemeQuery from "./SchemeQuery";
|
|||||||
import RecognitionResults from "./RecognitionResults";
|
import RecognitionResults from "./RecognitionResults";
|
||||||
import { getAreaColor } from "./utils";
|
import { getAreaColor } from "./utils";
|
||||||
import { LeakageResultDetail } from "./types";
|
import { LeakageResultDetail } from "./types";
|
||||||
|
import { config } from "@/config/config";
|
||||||
|
|
||||||
const TabPanel = ({
|
const TabPanel = ({
|
||||||
value,
|
value,
|
||||||
@@ -44,7 +44,7 @@ const TabPanel = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const DMA_AREA_INDEX_PROPERTY = "dma_area_index";
|
||||||
|
|
||||||
const DMALeakDetectionPanel: React.FC = () => {
|
const DMALeakDetectionPanel: React.FC = () => {
|
||||||
const map = useMap();
|
const map = useMap();
|
||||||
@@ -52,7 +52,6 @@ const DMALeakDetectionPanel: React.FC = () => {
|
|||||||
const [tab, setTab] = useState(0);
|
const [tab, setTab] = useState(0);
|
||||||
const [result, setResult] = useState<LeakageResultDetail | null>(null);
|
const [result, setResult] = useState<LeakageResultDetail | null>(null);
|
||||||
const [loadedResult, setLoadedResult] = useState<LeakageResultDetail | null>(null);
|
const [loadedResult, setLoadedResult] = useState<LeakageResultDetail | null>(null);
|
||||||
const [nodeLayer, setNodeLayer] = useState<VectorLayer<VectorSource> | null>(null);
|
|
||||||
|
|
||||||
const drawerWidth = 450;
|
const drawerWidth = 450;
|
||||||
const panelTitle = "DMA漏损识别";
|
const panelTitle = "DMA漏损识别";
|
||||||
@@ -70,55 +69,6 @@ const DMALeakDetectionPanel: React.FC = () => {
|
|||||||
[activeAreas.length],
|
[activeAreas.length],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!map) return;
|
|
||||||
const layer = new VectorLayer({
|
|
||||||
source: new VectorSource(),
|
|
||||||
maxZoom: 24,
|
|
||||||
minZoom: 12,
|
|
||||||
properties: {
|
|
||||||
name: "DMA漏损节点着色",
|
|
||||||
value: "dma_leak_nodes",
|
|
||||||
},
|
|
||||||
style: (feature) => {
|
|
||||||
const areaId = feature.get("__areaId");
|
|
||||||
return new Style({
|
|
||||||
image: new CircleStyle({
|
|
||||||
radius: 4.5,
|
|
||||||
fill: new Fill({ color: getAreaColor(areaId) }),
|
|
||||||
stroke: new Stroke({ color: "#ffffff", width: 1.2 }),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
map.addLayer(layer);
|
|
||||||
setNodeLayer(layer);
|
|
||||||
return () => {
|
|
||||||
map.removeLayer(layer);
|
|
||||||
};
|
|
||||||
}, [map]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!nodeLayer) return;
|
|
||||||
const source = nodeLayer.getSource();
|
|
||||||
if (!source) return;
|
|
||||||
source.clear();
|
|
||||||
if (!loadedResult) return;
|
|
||||||
|
|
||||||
const nodeAreaMap = loadedResult.node_area_map || {};
|
|
||||||
const nodeIds = Object.keys(nodeAreaMap);
|
|
||||||
if (nodeIds.length === 0) return;
|
|
||||||
|
|
||||||
queryFeaturesByIds(nodeIds, "geo_junctions_mat").then((features) => {
|
|
||||||
if (!features?.length) return;
|
|
||||||
features.forEach((feature) => {
|
|
||||||
const nodeId = String(feature.get("id") ?? "");
|
|
||||||
feature.set("__areaId", nodeAreaMap[nodeId] ?? "");
|
|
||||||
});
|
|
||||||
source.addFeatures(features as Feature[]);
|
|
||||||
});
|
|
||||||
}, [loadedResult, nodeLayer]);
|
|
||||||
|
|
||||||
const handleAnalysisResult = useCallback((res: LeakageResultDetail) => {
|
const handleAnalysisResult = useCallback((res: LeakageResultDetail) => {
|
||||||
setResult(res);
|
setResult(res);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -129,6 +79,105 @@ const DMALeakDetectionPanel: React.FC = () => {
|
|||||||
setTab(2);
|
setTab(2);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!map) return;
|
||||||
|
const junctionLayer = map
|
||||||
|
.getAllLayers()
|
||||||
|
.find(
|
||||||
|
(layer) =>
|
||||||
|
layer instanceof WebGLVectorTileLayer && layer.get("value") === "junctions",
|
||||||
|
) as WebGLVectorTileLayer | undefined;
|
||||||
|
if (!junctionLayer) return;
|
||||||
|
const source = junctionLayer.getSource() as VectorTileSource;
|
||||||
|
if (!source) return;
|
||||||
|
|
||||||
|
if (!loadedResult || !loadedResult.node_area_map) {
|
||||||
|
junctionLayer.setStyle(config.MAP_DEFAULT_STYLE as FlatStyleLike);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fallbackAreaIds = Array.from(
|
||||||
|
new Set(Object.values(loadedResult.node_area_map || {}).map(String)),
|
||||||
|
);
|
||||||
|
const areaIds = (loadedResult.areas || []).length
|
||||||
|
? loadedResult.areas.map((area) => String(area.area_id))
|
||||||
|
: fallbackAreaIds;
|
||||||
|
if (areaIds.length === 0) {
|
||||||
|
junctionLayer.setStyle(config.MAP_DEFAULT_STYLE as FlatStyleLike);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const areaIdToIndex = new Map<string, number>();
|
||||||
|
areaIds.forEach((areaId, index) => {
|
||||||
|
areaIdToIndex.set(areaId, index + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeAreaIndexMap = new Map<string, number>();
|
||||||
|
Object.entries(loadedResult.node_area_map || {}).forEach(([nodeId, areaId]) => {
|
||||||
|
const idx = areaIdToIndex.get(String(areaId));
|
||||||
|
if (idx !== undefined) {
|
||||||
|
nodeAreaIndexMap.set(String(nodeId), idx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const applyFeatureAreaIndex = (renderFeature: any) => {
|
||||||
|
const featureId = String(renderFeature.get("id") ?? "");
|
||||||
|
const areaIndex = nodeAreaIndexMap.get(featureId);
|
||||||
|
if (areaIndex !== undefined) {
|
||||||
|
renderFeature.properties_[DMA_AREA_INDEX_PROPERTY] = areaIndex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceTiles = (source as any).sourceTiles_;
|
||||||
|
if (sourceTiles) {
|
||||||
|
Object.values(sourceTiles).forEach((vectorTile: any) => {
|
||||||
|
const renderFeatures = vectorTile.getFeatures();
|
||||||
|
if (!renderFeatures || renderFeatures.length === 0) return;
|
||||||
|
renderFeatures.forEach((renderFeature: any) => {
|
||||||
|
applyFeatureAreaIndex(renderFeature);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const listener = (event: any) => {
|
||||||
|
try {
|
||||||
|
if (event.tile instanceof VectorTile) {
|
||||||
|
const renderFeatures = event.tile.getFeatures();
|
||||||
|
if (!renderFeatures || renderFeatures.length === 0) return;
|
||||||
|
renderFeatures.forEach((renderFeature: any) => {
|
||||||
|
applyFeatureAreaIndex(renderFeature);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error applying DMA area mapping:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
source.on("tileloadend", listener);
|
||||||
|
|
||||||
|
const fillCases: any[] = [];
|
||||||
|
areaIds.forEach((areaId, index) => {
|
||||||
|
fillCases.push(
|
||||||
|
["==", ["get", DMA_AREA_INDEX_PROPERTY], index + 1],
|
||||||
|
getAreaColor(areaId),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const defaultFillColor = String(config.MAP_DEFAULT_STYLE["circle-fill-color"]);
|
||||||
|
const defaultStrokeColor = String(
|
||||||
|
config.MAP_DEFAULT_STYLE["circle-stroke-color"],
|
||||||
|
);
|
||||||
|
const dmaStyle: FlatStyleLike = {
|
||||||
|
...config.MAP_DEFAULT_STYLE,
|
||||||
|
"circle-fill-color": ["case", ...fillCases, defaultFillColor],
|
||||||
|
"circle-stroke-color": ["case", ...fillCases, defaultStrokeColor],
|
||||||
|
};
|
||||||
|
junctionLayer.setStyle(dmaStyle);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
source.un("tileloadend", listener);
|
||||||
|
junctionLayer.setStyle(config.MAP_DEFAULT_STYLE as FlatStyleLike);
|
||||||
|
};
|
||||||
|
}, [map, loadedResult]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!open && (
|
{!open && (
|
||||||
|
|||||||
Reference in New Issue
Block a user