完善图例和样式设置;调整属性框的最大长度
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user