完善图例和样式设置;调整属性框的最大长度

This commit is contained in:
JIANG
2025-11-21 11:15:03 +08:00
parent 23154b2b5f
commit 15e80f105e
3 changed files with 83 additions and 42 deletions

View File

@@ -50,7 +50,7 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
: 0; : 0;
return ( return (
<div className="absolute top-4 right-4 bg-white shadow-2xl rounded-xl overflow-hidden w-96 z-10 max-h[850px] flex flex-col backdrop-blur-sm opacity-95 hover:opacity-100 transition-all duration-300"> <div className="absolute top-4 right-4 bg-white shadow-2xl rounded-xl overflow-hidden w-96 max-h-[850px] flex flex-col backdrop-blur-sm z-50 opacity-95 hover:opacity-100 transition-all duration-300 ">
{/* 头部 */} {/* 头部 */}
<div className="flex justify-between items-center px-5 py-4 bg-[#257DD4] text-white"> <div className="flex justify-between items-center px-5 py-4 bg-[#257DD4] text-white">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@@ -31,6 +31,7 @@ import { parseColor } from "@utils/parseColor";
import { VectorTile } from "ol"; import { VectorTile } from "ol";
import { useNotification } from "@refinedev/core"; import { useNotification } from "@refinedev/core";
import { config } from "@/config/config"; import { config } from "@/config/config";
import { constructNow, min } from "date-fns";
interface StyleConfig { interface StyleConfig {
property: string; property: string;
@@ -401,8 +402,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
junctionStyleConfigState?.styleConfig.classificationMethod === junctionStyleConfigState?.styleConfig.classificationMethod ===
"custom_breaks" "custom_breaks"
) { ) {
// 使用自定义断点(保证为 segments + 1 个断点,按升序) // 使用自定义断点(保证为 segments 个断点,按升序)
const desired = segments + 1; const desired = segments;
breaks = ( breaks = (
junctionStyleConfigState?.styleConfig.customBreaks || [] junctionStyleConfigState?.styleConfig.customBreaks || []
).slice(0, desired); ).slice(0, desired);
@@ -412,6 +413,7 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
// 如果不足则补齐最后一个值 // 如果不足则补齐最后一个值
while (breaks.length < desired) while (breaks.length < desired)
breaks.push(breaks[breaks.length - 1] ?? 0); breaks.push(breaks[breaks.length - 1] ?? 0);
console.log(breaks);
} else { } else {
const calc = calculateClassification( const calc = calculateClassification(
currentJunctionCalData.map((d) => d.value), currentJunctionCalData.map((d) => d.value),
@@ -424,6 +426,21 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
console.warn("计算的 breaks 为空,无法应用样式"); console.warn("计算的 breaks 为空,无法应用样式");
return; return;
} }
// 计算最大最小值,判断是否包含并插入 breaks
const data = currentJunctionCalData.map((d) => d.value);
const min_val = Math.max(
data.reduce((min, val) => Math.min(min, val), Infinity),
0
);
const max_val = data.reduce((max, val) => Math.max(max, val), -Infinity);
if (breaks.includes(min_val) === false) {
breaks.push(min_val);
breaks.sort((a, b) => a - b);
}
if (breaks.includes(max_val) === false) {
breaks.push(max_val);
breaks.sort((a, b) => a - b);
}
if (junctionStyleConfigState) if (junctionStyleConfigState)
applyLayerStyle(junctionStyleConfigState, breaks); applyLayerStyle(junctionStyleConfigState, breaks);
} else if ( } else if (
@@ -442,8 +459,8 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
pipeStyleConfigState?.styleConfig.classificationMethod === pipeStyleConfigState?.styleConfig.classificationMethod ===
"custom_breaks" "custom_breaks"
) { ) {
// 使用自定义断点(保证为 segments + 1 个断点,按升序) // 使用自定义断点(保证为 segments 个断点,按升序)
const desired = segments + 1; const desired = segments;
breaks = (pipeStyleConfigState?.styleConfig.customBreaks || []).slice( breaks = (pipeStyleConfigState?.styleConfig.customBreaks || []).slice(
0, 0,
desired desired
@@ -460,6 +477,25 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
); );
breaks = calc; breaks = calc;
} }
if (breaks.length === 0) {
console.warn("计算的 breaks 为空,无法应用样式");
return;
}
// 计算最大最小值,判断是否包含并插入 breaks
const data = currentPipeCalData.map((d) => d.value);
const min_val = Math.max(
data.reduce((min, val) => Math.min(min, val), Infinity),
0
);
const max_val = data.reduce((max, val) => Math.max(max, val), -Infinity);
if (breaks.includes(min_val) === false) {
breaks.push(min_val);
breaks.sort((a, b) => a - b);
}
if (breaks.includes(max_val) === false) {
breaks.push(max_val);
breaks.sort((a, b) => a - b);
}
if (pipeStyleConfigState) applyLayerStyle(pipeStyleConfigState, breaks); if (pipeStyleConfigState) applyLayerStyle(pipeStyleConfigState, breaks);
} }
}; };
@@ -497,10 +533,15 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
: (() => { : (() => {
// 自定义颜色 // 自定义颜色
const custom = styleConfig.customColors || []; const custom = styleConfig.customColors || [];
// 如果自定义颜色数量不足,用默认颜色补齐(这里简单用红色,或者重复最后一个) // 如果自定义颜色数量不足,用反向彩虹色填充
const result = [...custom]; const result = [...custom];
const reverseRainbowColors = RAINBOW_PALETTES[1].colors;
while (result.length < breaksLength) { while (result.length < breaksLength) {
result.push(result[result.length - 1] || "rgba(255, 0, 0, 1)"); result.push(
reverseRainbowColors[
(result.length - custom.length) % reverseRainbowColors.length
]
);
} }
return result.slice(0, breaksLength); return result.slice(0, breaksLength);
})(); })();
@@ -531,17 +572,17 @@ const StyleEditorPanel: React.FC<StyleEditorPanelProps> = ({
// 动态生成颜色条件表达式 // 动态生成颜色条件表达式
const generateColorConditions = (property: string): any[] => { const generateColorConditions = (property: string): any[] => {
const conditions: any[] = ["case"]; const conditions: any[] = ["case"];
for (let i = 0; i < breaks.length; i++) { for (let i = 1; i < breaks.length; i++) {
// 添加条件:属性值 <= 当前断点 // 添加条件:属性值 <= 当前断点
conditions.push(["<=", ["get", property], breaks[i]]); conditions.push(["<=", ["get", property], breaks[i]]);
// 添加对应的颜色值 // 添加对应的颜色值
const colorObj = parseColor(colors[i]); const colorObj = parseColor(colors[i - 1]);
const color = `rgba(${colorObj.r}, ${colorObj.g}, ${colorObj.b}, ${styleConfig.opacity})`; const color = `rgba(${colorObj.r}, ${colorObj.g}, ${colorObj.b}, ${styleConfig.opacity})`;
conditions.push(color); conditions.push(color);
} }
const colorObj = parseColor(colors[colors.length - 1]); const colorObj = parseColor(colors[0]);
const color = `rgba(${colorObj.r}, ${colorObj.g}, ${colorObj.b}, ${styleConfig.opacity})`; const color = `rgba(${colorObj.r}, ${colorObj.g}, ${colorObj.b}, ${styleConfig.opacity})`;
// 添加默认值(最后一个颜色) // 添加默认值(个颜色)
conditions.push(color); conditions.push(color);
return conditions; return conditions;
}; };

View File

@@ -36,38 +36,38 @@ const StyleLegend: React.FC<LegendStyleConfig> = ({
const color = colors[index]; // 默认颜色为黑色 const color = colors[index]; // 默认颜色为黑色
const dimension = dimensions[index]; // 默认尺寸为16 const dimension = dimensions[index]; // 默认尺寸为16
// 处理第一个区间(小于 breaks[0] // // 处理第一个区间(小于 breaks[0]
if (index === 0) { // if (index === 0) {
return ( // return (
<Box key={index} className="flex items-center gap-2 mb-1"> // <Box key={index} className="flex items-center gap-2 mb-1">
<Box // <Box
sx={ // sx={
type === "point" // type === "point"
? { // ? {
width: dimension, // width: dimension,
height: dimension, // height: dimension,
borderRadius: "50%", // borderRadius: "50%",
backgroundColor: color, // backgroundColor: color,
} // }
: { // : {
width: 16, // width: 16,
height: dimension, // height: dimension,
backgroundColor: color, // backgroundColor: color,
border: `1px solid ${color}`, // border: `1px solid ${color}`,
} // }
} // }
/> // />
<Typography variant="caption" className="text-xs"> // <Typography variant="caption" className="text-xs">
{"<"} {breaks[0]?.toFixed(1)} // {"<"} {breaks[0]?.toFixed(1)}
</Typography> // </Typography>
</Box> // </Box>
); // );
} // }
// 处理中间区间breaks[index-1] - breaks[index] // 处理中间区间breaks[index] - breaks[index + 1]
if (index < breaks.length) { if (index + 1 < breaks.length) {
const prevValue = breaks[index - 1]; const prevValue = breaks[index];
const currentValue = breaks[index]; const currentValue = breaks[index + 1];
return ( return (
<Box key={index} className="flex items-center gap-2 mb-1"> <Box key={index} className="flex items-center gap-2 mb-1">
<Box <Box