新增固有属性的样式计算
This commit is contained in:
@@ -195,6 +195,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
setJunctionText,
|
||||
setPipeText,
|
||||
setContours,
|
||||
diameterRange,
|
||||
elevationRange,
|
||||
} = data;
|
||||
|
||||
const { open } = useNotification();
|
||||
@@ -398,10 +400,15 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
layerType: "junctions" | "pipes",
|
||||
styleConfig: any
|
||||
) => {
|
||||
const isElevation =
|
||||
layerType === "junctions" && styleConfig.property === "elevation";
|
||||
const isDiameter =
|
||||
layerType === "pipes" && styleConfig.property === "diameter";
|
||||
|
||||
if (
|
||||
layerType === "junctions" &&
|
||||
currentJunctionCalData &&
|
||||
currentJunctionCalData.length > 0
|
||||
((currentJunctionCalData && currentJunctionCalData.length > 0) ||
|
||||
(isElevation && elevationRange))
|
||||
) {
|
||||
// 应用节点样式
|
||||
let junctionStyleConfigState = layerStyleStates.find(
|
||||
@@ -411,6 +418,14 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
// 更新节点数据属性
|
||||
const segments = junctionStyleConfigState?.styleConfig.segments ?? 5;
|
||||
let breaks: number[] = [];
|
||||
|
||||
const dataValues =
|
||||
isElevation && elevationRange
|
||||
? [elevationRange[0], elevationRange[1]]
|
||||
: currentJunctionCalData?.map((d: any) => d.value) || [];
|
||||
|
||||
if (dataValues.length === 0) return;
|
||||
|
||||
if (
|
||||
junctionStyleConfigState?.styleConfig.classificationMethod ===
|
||||
"custom_breaks"
|
||||
@@ -428,7 +443,7 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
breaks.push(breaks[breaks.length - 1] ?? 0);
|
||||
} else {
|
||||
const calc = calculateClassification(
|
||||
currentJunctionCalData.map((d) => d.value),
|
||||
dataValues,
|
||||
segments,
|
||||
styleConfig.classificationMethod
|
||||
);
|
||||
@@ -439,12 +454,14 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
return;
|
||||
}
|
||||
// 计算最大最小值,判断是否包含并插入 breaks
|
||||
const data = currentJunctionCalData.map((d) => d.value);
|
||||
const min_val = Math.max(
|
||||
data.reduce((min, val) => Math.min(min, val), Infinity),
|
||||
dataValues.reduce((min, val) => Math.min(min, val), Infinity),
|
||||
0
|
||||
);
|
||||
const max_val = data.reduce((max, val) => Math.max(max, val), -Infinity);
|
||||
const max_val = dataValues.reduce(
|
||||
(max, val) => Math.max(max, val),
|
||||
-Infinity
|
||||
);
|
||||
if (breaks.includes(min_val) === false) {
|
||||
breaks.push(min_val);
|
||||
breaks.sort((a, b) => a - b);
|
||||
@@ -459,8 +476,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
}
|
||||
} else if (
|
||||
layerType === "pipes" &&
|
||||
currentPipeCalData &&
|
||||
currentPipeCalData.length > 0
|
||||
((currentPipeCalData && currentPipeCalData.length > 0) ||
|
||||
(isDiameter && diameterRange))
|
||||
) {
|
||||
// 应用管道样式
|
||||
let pipeStyleConfigState = layerStyleStates.find(
|
||||
@@ -469,6 +486,14 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
// 更新管道数据属性
|
||||
const segments = pipeStyleConfigState?.styleConfig.segments ?? 5;
|
||||
let breaks: number[] = [];
|
||||
|
||||
const dataValues =
|
||||
isDiameter && diameterRange
|
||||
? [diameterRange[0], diameterRange[1]]
|
||||
: currentPipeCalData?.map((d: any) => d.value) || [];
|
||||
|
||||
if (dataValues.length === 0) return;
|
||||
|
||||
if (
|
||||
pipeStyleConfigState?.styleConfig.classificationMethod ===
|
||||
"custom_breaks"
|
||||
@@ -485,7 +510,7 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
breaks.push(breaks[breaks.length - 1] ?? 0);
|
||||
} else {
|
||||
const calc = calculateClassification(
|
||||
currentPipeCalData.map((d) => d.value),
|
||||
dataValues,
|
||||
segments,
|
||||
styleConfig.classificationMethod
|
||||
);
|
||||
@@ -496,12 +521,14 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
return;
|
||||
}
|
||||
// 计算最大最小值,判断是否包含并插入 breaks
|
||||
const data = currentPipeCalData.map((d) => d.value);
|
||||
const min_val = Math.max(
|
||||
data.reduce((min, val) => Math.min(min, val), Infinity),
|
||||
dataValues.reduce((min, val) => Math.min(min, val), Infinity),
|
||||
0
|
||||
);
|
||||
const max_val = data.reduce((max, val) => Math.max(max, val), -Infinity);
|
||||
const max_val = dataValues.reduce(
|
||||
(max, val) => Math.max(max, val),
|
||||
-Infinity
|
||||
);
|
||||
if (breaks.includes(min_val) === false) {
|
||||
breaks.push(min_val);
|
||||
breaks.sort((a, b) => a - b);
|
||||
@@ -883,16 +910,25 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
prevStyleUpdateTriggerRef.current = styleUpdateTrigger;
|
||||
|
||||
const updateJunctionStyle = () => {
|
||||
if (!currentJunctionCalData) return;
|
||||
const junctionStyleConfigState = layerStyleStates.find(
|
||||
(s) => s.layerId === "junctions"
|
||||
);
|
||||
const isElevation =
|
||||
junctionStyleConfigState?.styleConfig.property === "elevation";
|
||||
|
||||
// setStyle() 会清除渲染器缓存,这是闪烁的主要原因 WebGLVectorTile.js:114-118
|
||||
// 尝试考虑使用 updateStyleVariables() 更新
|
||||
applyClassificationStyle(
|
||||
"junctions",
|
||||
junctionStyleConfigState?.styleConfig
|
||||
);
|
||||
|
||||
if (isElevation) {
|
||||
removeVectorTileSourceLoadedEvent("junctions");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentJunctionCalData) return;
|
||||
// 更新现有的 VectorTileSource
|
||||
updateVectorTileSource(junctionText, currentJunctionCalData);
|
||||
// 移除旧的监听器,并添加新的监听器
|
||||
@@ -904,11 +940,20 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
);
|
||||
};
|
||||
const updatePipeStyle = () => {
|
||||
if (!currentPipeCalData) return;
|
||||
const pipeStyleConfigState = layerStyleStates.find(
|
||||
(s) => s.layerId === "pipes"
|
||||
);
|
||||
const isDiameter =
|
||||
pipeStyleConfigState?.styleConfig.property === "diameter";
|
||||
|
||||
applyClassificationStyle("pipes", pipeStyleConfigState?.styleConfig);
|
||||
|
||||
if (isDiameter) {
|
||||
removeVectorTileSourceLoadedEvent("pipes");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentPipeCalData) return;
|
||||
// 更新现有的 VectorTileSource
|
||||
updateVectorTileSource(pipeText, currentPipeCalData);
|
||||
// 移除旧的监听器,并添加新的监听器
|
||||
@@ -923,14 +968,21 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const isElevation = junctionText === "elevation";
|
||||
const isDiameter = pipeText === "diameter";
|
||||
|
||||
if (
|
||||
applyJunctionStyle &&
|
||||
currentJunctionCalData &&
|
||||
currentJunctionCalData.length > 0
|
||||
((currentJunctionCalData && currentJunctionCalData.length > 0) ||
|
||||
isElevation)
|
||||
) {
|
||||
updateJunctionStyle();
|
||||
}
|
||||
if (applyPipeStyle && currentPipeCalData && currentPipeCalData.length > 0) {
|
||||
if (
|
||||
applyPipeStyle &&
|
||||
((currentPipeCalData && currentPipeCalData.length > 0) || isDiameter)
|
||||
) {
|
||||
updatePipeStyle();
|
||||
}
|
||||
if (!applyJunctionStyle) {
|
||||
@@ -945,6 +997,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
applyPipeStyle,
|
||||
currentJunctionCalData,
|
||||
currentPipeCalData,
|
||||
elevationRange,
|
||||
diameterRange,
|
||||
]);
|
||||
|
||||
// 获取地图中的矢量图层,用于选择图层选项
|
||||
@@ -1018,10 +1072,21 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
|
||||
const selectedLayerId = selectedRenderLayer?.get("value");
|
||||
let dataArr: number[] = [];
|
||||
if (selectedLayerId === "junctions" && currentJunctionCalData)
|
||||
dataArr = currentJunctionCalData.map((d) => d.value);
|
||||
else if (selectedLayerId === "pipes" && currentPipeCalData)
|
||||
dataArr = currentPipeCalData.map((d) => d.value);
|
||||
|
||||
const isElevation =
|
||||
selectedLayerId === "junctions" && styleConfig.property === "elevation";
|
||||
const isDiameter =
|
||||
selectedLayerId === "pipes" && styleConfig.property === "diameter";
|
||||
|
||||
if (isElevation && elevationRange) {
|
||||
dataArr = [elevationRange[0], elevationRange[1]];
|
||||
} else if (isDiameter && diameterRange) {
|
||||
dataArr = [diameterRange[0], diameterRange[1]];
|
||||
} else if (selectedLayerId === "junctions" && currentJunctionCalData) {
|
||||
dataArr = currentJunctionCalData.map((d: any) => d.value);
|
||||
} else if (selectedLayerId === "pipes" && currentPipeCalData) {
|
||||
dataArr = currentPipeCalData.map((d: any) => d.value);
|
||||
}
|
||||
|
||||
let defaultBreaks: number[] = Array.from({ length: numBreaks }, () => 0);
|
||||
if (dataArr && dataArr.length > 0) {
|
||||
@@ -1041,9 +1106,12 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
|
||||
}, [
|
||||
styleConfig.classificationMethod,
|
||||
styleConfig.segments,
|
||||
styleConfig.property,
|
||||
selectedRenderLayer,
|
||||
currentJunctionCalData,
|
||||
currentPipeCalData,
|
||||
elevationRange,
|
||||
diameterRange,
|
||||
]);
|
||||
|
||||
// 初始化或调整自定义颜色数组长度
|
||||
|
||||
@@ -63,6 +63,8 @@ interface DataContextType {
|
||||
setPipeText?: React.Dispatch<React.SetStateAction<string>>;
|
||||
setContours?: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
deckLayer?: DeckLayer;
|
||||
diameterRange?: [number, number];
|
||||
elevationRange?: [number, number];
|
||||
}
|
||||
|
||||
// 跨组件传递
|
||||
@@ -130,6 +132,13 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
const [showWaterflowLayer, setShowWaterflowLayer] = useState(false); // 控制等高线图层显示
|
||||
const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别
|
||||
|
||||
const [diameterRange, setDiameterRange] = useState<
|
||||
[number, number] | undefined
|
||||
>();
|
||||
const [elevationRange, setElevationRange] = useState<
|
||||
[number, number] | undefined
|
||||
>();
|
||||
|
||||
// 防抖更新函数
|
||||
const debouncedUpdateData = useRef(
|
||||
debounce(() => {
|
||||
@@ -155,6 +164,24 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
});
|
||||
if (uniqueNewData.length > 0) {
|
||||
setJunctionDataState((prev) => prev.concat(uniqueNewData));
|
||||
setElevationRange((prev) => {
|
||||
const elevations = uniqueNewData
|
||||
.map((d) => d.elevation)
|
||||
.filter((v) => typeof v === "number");
|
||||
if (elevations.length === 0) return prev;
|
||||
|
||||
let newMin = elevations[0];
|
||||
let newMax = elevations[0];
|
||||
for (let i = 1; i < elevations.length; i++) {
|
||||
if (elevations[i] < newMin) newMin = elevations[i];
|
||||
if (elevations[i] > newMax) newMax = elevations[i];
|
||||
}
|
||||
|
||||
if (!prev) {
|
||||
return [newMin, newMax];
|
||||
}
|
||||
return [Math.min(prev[0], newMin), Math.max(prev[1], newMax)];
|
||||
});
|
||||
}
|
||||
};
|
||||
const setPipeData = (newData: any[]) => {
|
||||
@@ -168,6 +195,24 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
});
|
||||
if (uniqueNewData.length > 0) {
|
||||
setPipeDataState((prev) => prev.concat(uniqueNewData));
|
||||
setDiameterRange((prev) => {
|
||||
const diameters = uniqueNewData
|
||||
.map((d) => d.diameter)
|
||||
.filter((v) => typeof v === "number");
|
||||
if (diameters.length === 0) return prev;
|
||||
|
||||
let newMin = diameters[0];
|
||||
let newMax = diameters[0];
|
||||
for (let i = 1; i < diameters.length; i++) {
|
||||
if (diameters[i] < newMin) newMin = diameters[i];
|
||||
if (diameters[i] > newMax) newMax = diameters[i];
|
||||
}
|
||||
|
||||
if (!prev) {
|
||||
return [newMin, newMax];
|
||||
}
|
||||
return [Math.min(prev[0], newMin), Math.max(prev[1], newMax)];
|
||||
});
|
||||
}
|
||||
};
|
||||
// 配置地图数据源、图层和样式
|
||||
@@ -295,8 +340,8 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
// { name: "需求量", value: "demand" },
|
||||
{ name: "高程", value: "elevation" },
|
||||
// 计算属性
|
||||
{ name: "实际需求量", value: "actualdemand" },
|
||||
{ name: "水头", value: "head" },
|
||||
{ name: "实际需水量", value: "actual_demand" },
|
||||
{ name: "水头", value: "total_head" },
|
||||
{ name: "压力", value: "pressure" },
|
||||
{ name: "水质", value: "quality" },
|
||||
],
|
||||
@@ -985,6 +1030,8 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
||||
pipeText,
|
||||
setContours,
|
||||
deckLayer,
|
||||
diameterRange,
|
||||
elevationRange,
|
||||
}}
|
||||
>
|
||||
<MapContext.Provider value={map}>
|
||||
|
||||
Reference in New Issue
Block a user