持久化样式状态;分离样式设置和图例显示;完成时间轴组件代码修复建议

This commit is contained in:
JIANG
2025-10-20 11:15:49 +08:00
parent 4e819b20ea
commit f62ab1c30e
3 changed files with 77 additions and 65 deletions

View File

@@ -22,7 +22,7 @@ import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
import VectorTileSource from "ol/source/VectorTile";
import { useData, useMap } from "../MapComponent";
import StyleLegend, { LegendStyleConfig } from "./StyleLegend";
import { LegendStyleConfig } from "./StyleLegend";
import { FlatStyleLike } from "ol/style/flat";
import { calculateClassification } from "@utils/breaks_classification";
@@ -55,7 +55,10 @@ interface LayerStyleState {
legendConfig: LegendStyleConfig;
isActive: boolean;
}
// 持久化存储
const STORAGE_KEYS = {
layerStyleStates: "styleEditor_layerStyleStates",
};
// 预设颜色方案
const SINGLE_COLOR_PALETTES = [
{
@@ -116,6 +119,7 @@ const StyleEditorPanel: React.FC = () => {
setShowPipeText,
setJunctionText,
setPipeText,
updateLegendConfigs,
} = data;
const { open, close } = useNotification();
@@ -128,11 +132,6 @@ const StyleEditorPanel: React.FC = () => {
const [renderLayers, setRenderLayers] = useState<WebGLVectorTileLayer[]>([]);
const [selectedRenderLayer, setSelectedRenderLayer] =
useState<WebGLVectorTileLayer>();
const [selectedProperty, setSelectedProperty] = useState<{
name: string;
value: string;
}>({ name: "", value: "" });
const [availableProperties, setAvailableProperties] = useState<
{ name: string; value: string }[]
>([]);
@@ -154,8 +153,18 @@ const StyleEditorPanel: React.FC = () => {
});
// 样式状态管理 - 存储多个图层的样式状态
const [layerStyleStates, setLayerStyleStates] = useState<LayerStyleState[]>(
[]
() => {
const saved = sessionStorage.getItem(STORAGE_KEYS.layerStyleStates);
return saved ? JSON.parse(saved) : [];
}
);
// 保存layerStyleStates到sessionStorage
useEffect(() => {
sessionStorage.setItem(
STORAGE_KEYS.layerStyleStates,
JSON.stringify(layerStyleStates)
);
}, [layerStyleStates]);
// 颜色方案选择
const [singlePaletteIndex, setSinglePaletteIndex] = useState(0);
const [gradientPaletteIndex, setGradientPaletteIndex] = useState(0);
@@ -186,31 +195,37 @@ const StyleEditorPanel: React.FC = () => {
);
// 保存当前图层的样式状态
const saveLayerStyle = useCallback(
(layerId?: string, legendConfig?: LegendStyleConfig) => {
(layerId?: string, newLegendConfig?: LegendStyleConfig) => {
if (!selectedRenderLayer || !styleConfig.property) {
console.warn("无法保存样式:缺少必要的图层或样式配置");
return;
}
if (!layerId) return; // 如果没有传入 layerId则不保存
const layerName = selectedRenderLayer.get("name") || `图层${layerId}`;
// 如果没有传入图例配置,则创建一个默认的空配置
const finalLegendConfig: LegendStyleConfig = legendConfig || {
const layerName =
newLegendConfig?.layerName ||
selectedRenderLayer.get("name") ||
`图层${layerId}`;
const property = availableProperties.find(
(p) => p.value === styleConfig.property
);
let legendConfig: LegendStyleConfig = newLegendConfig || {
layerId,
layerName,
property: selectedProperty.name,
property: property?.name || styleConfig.property,
colors: [],
type: "point",
type: selectedRenderLayer.get("type"),
dimensions: [],
breaks: [],
};
const newStyleState: LayerStyleState = {
layerId,
layerName,
styleConfig: { ...styleConfig },
legendConfig: { ...finalLegendConfig },
legendConfig: { ...legendConfig },
isActive: true,
};
setLayerStyleStates((prev) => {
// 检查是否已存在该图层的样式状态
const existingIndex = prev.findIndex(
@@ -323,12 +338,12 @@ const StyleEditorPanel: React.FC = () => {
return;
}
const styleConfig = layerStyleConfig.styleConfig;
const selectedRenderLayer = renderLayers.filter((layer) => {
const renderLayer = renderLayers.filter((layer) => {
return layer.get("value") === layerStyleConfig.layerId;
})[0];
if (!selectedRenderLayer || !styleConfig?.property) return;
const layerType: string = selectedRenderLayer?.get("type");
const source = selectedRenderLayer.getSource();
if (!renderLayer || !styleConfig?.property) return;
const layerType: string = renderLayer?.get("type");
const source = renderLayer.getSource();
if (!source) return;
const breaksLength = breaks.length;
@@ -416,13 +431,17 @@ const StyleEditorPanel: React.FC = () => {
dynamicStyle["circle-stroke-width"] = 2;
}
selectedRenderLayer.setStyle(dynamicStyle);
renderLayer.setStyle(dynamicStyle);
// 用初始化时的样式配置更新图例配置,避免覆盖已有的图例名称和属性
const layerId = renderLayer.get("value");
const initLayerStyleState = layerStyleStates.find(
(s) => s.layerId === layerId
);
// 创建图例配置对象
const legendConfig: LegendStyleConfig = {
layerName: selectedRenderLayer.get("name"),
layerId: selectedRenderLayer.get("value"),
property: selectedProperty.name,
layerName: initLayerStyleState?.layerName || `图层${layerId}`,
layerId: layerId,
property: initLayerStyleState?.legendConfig.property || "",
colors: colors,
type: layerType,
dimensions: dimensions,
@@ -430,7 +449,7 @@ const StyleEditorPanel: React.FC = () => {
};
// 自动保存样式状态,直接传入图例配置
setTimeout(() => {
saveLayerStyle(selectedRenderLayer.get("value"), legendConfig);
saveLayerStyle(renderLayer.get("value"), legendConfig);
}, 100);
};
// 重置样式
@@ -695,20 +714,7 @@ const StyleEditorPanel: React.FC = () => {
setStyleConfig(cachedStyleState.styleConfig);
}
}, [renderLayers, selectedRenderLayer, map, renderLayers, layerStyleStates]);
// 同步属性状态
useEffect(() => {
// 当属性值变化时自动同步 selectedProperty
if (styleConfig.property) {
const prop = availableProperties.find(
(p) => p.value === styleConfig.property
);
if (prop) {
setSelectedProperty({ name: prop.name, value: prop.value });
}
} else {
setSelectedProperty({ name: "", value: "" });
}
}, [styleConfig.property, availableProperties]);
// 监听颜色类型变化,当切换到单一色时自动勾选宽度调整选项
useEffect(() => {
if (styleConfig.colorType === "single") {
@@ -720,14 +726,17 @@ const StyleEditorPanel: React.FC = () => {
}, [styleConfig.colorType]);
// 获取所有激活的图例配置
const getActiveLegendConfigs = useCallback(() => {
return layerStyleStates
.filter((state) => state.isActive && state.legendConfig.property)
.map((state) => ({
...state.legendConfig,
layerName: state.layerName,
layerId: state.layerId,
}));
useEffect(() => {
if (!updateLegendConfigs) return;
updateLegendConfigs(
layerStyleStates
.filter((state) => state.isActive && state.legendConfig.property)
.map((state) => ({
...state.legendConfig,
layerName: state.layerName,
layerId: state.layerId,
}))
);
}, [layerStyleStates]);
const getColorSetting = () => {
@@ -1184,16 +1193,6 @@ const StyleEditorPanel: React.FC = () => {
</Button>
</Box>
</div>
{/* 显示多图层图例 */}
{getActiveLegendConfigs().length > 0 && (
<div className=" absolute bottom-40 right-4 drop-shadow-xl flex flex-row items-end max-w-screen-lg overflow-x-auto z-10">
<div className="flex flex-row gap-3">
{getActiveLegendConfigs().map((config, index) => (
<StyleLegend key={`${config.layerId}-${index}`} {...config} />
))}
</div>
</div>
)}
</>
);
};