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