import React, { useState, useEffect, useCallback, useRef } from "react"; // 导入Material-UI图标和组件 import ColorLensIcon from "@mui/icons-material/ColorLens"; import ApplyIcon from "@mui/icons-material/Check"; import ResetIcon from "@mui/icons-material/Refresh"; import { Select, MenuItem, FormControl, InputLabel, Slider, Typography, Button, Box, Checkbox, FormControlLabel, } from "@mui/material"; // 导入OpenLayers样式相关模块 import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile"; import VectorTileSource from "ol/source/VectorTile"; import { useData, useMap } from "../MapComponent"; import { LegendStyleConfig } from "./StyleLegend"; import { FlatStyleLike } from "ol/style/flat"; import { calculateClassification } from "@utils/breaks_classification"; import { parseColor } from "@utils/parseColor"; import { VectorTile } from "ol"; import { useNotification } from "@refinedev/core"; import { config } from "@/config/config"; interface StyleConfig { property: string; classificationMethod: string; // 分类方法 segments: number; minSize: number; // 最小点尺寸 maxSize: number; // 最大点尺寸 minStrokeWidth: number; // 最小线宽 maxStrokeWidth: number; // 最大线宽 fixedStrokeWidth: number; // 固定线宽 colorType: string; // 颜色类型 startColor: string; endColor: string; showLabels: boolean; opacity: number; adjustWidthByProperty: boolean; // 是否根据属性调整线条宽度 } // 图层样式状态接口 interface LayerStyleState { layerId: string; layerName: string; styleConfig: StyleConfig; legendConfig: LegendStyleConfig; isActive: boolean; } // StyleEditorPanel 组件 Props 接口 interface StyleEditorPanelProps { layerStyleStates: LayerStyleState[]; setLayerStyleStates: React.Dispatch>; } // 预设颜色方案 const SINGLE_COLOR_PALETTES = [ { color: "rgba(51, 153, 204, 1)", }, { color: "rgba(255, 138, 92, 1)", }, { color: "rgba(204, 51, 51, 1)", }, { color: "rgba(255, 235, 59, 1)", }, { color: "rgba(44, 160, 44, 1)", }, { color: "rgba(227, 119, 194, 1)", }, { color: "rgba(148, 103, 189, 1)", }, ]; const GRADIENT_PALETTES = [ { name: "蓝-红", start: "rgba(51, 153, 204, 1)", end: "rgba(204, 51, 51, 1)", }, { name: "黄-绿", start: "rgba(255, 235, 59, 1)", end: "rgba(44, 160, 44, 1)", }, { name: "粉-紫", start: "rgba(227, 119, 194, 1)", end: "rgba(148, 103, 189, 1)", }, ]; // 离散彩虹色系 - 提供高区分度的颜色 const RAINBOW_PALETTES = [ { name: "正向彩虹", colors: [ "rgba(255, 0, 0, 1)", // 红 #FF0000 "rgba(255, 127, 0, 1)", // 橙 #FF7F00 "rgba(255, 215, 0, 1)", // 金黄 #FFD700 "rgba(199, 224, 0, 1)", // 黄绿 #C7E000 "rgba(76, 175, 80, 1)", // 中绿 #4CAF50 "rgba(0, 158, 115, 1)", // 青绿/翡翠 #009E73 "rgba(0, 188, 212, 1)", // 青/青色 #00BCD4 "rgba(33, 150, 243, 1)", // 天蓝 #2196F3 "rgba(63, 81, 181, 1)", // 靛青 #3F51B5 "rgba(142, 68, 173, 1)", // 紫 #8E44AD ], }, { name: "反向彩虹", colors: [ "rgba(142, 68, 173, 1)", // 紫 #8E44AD "rgba(63, 81, 181, 1)", // 靛青 #3F51B5 "rgba(33, 150, 243, 1)", // 天蓝 #2196F3 "rgba(0, 188, 212, 1)", // 青/青色 #00BCD4 "rgba(0, 158, 115, 1)", // 青绿/翡翠 #009E73 "rgba(76, 175, 80, 1)", // 中绿 #4CAF50 "rgba(199, 224, 0, 1)", // 黄绿 #C7E000 "rgba(255, 215, 0, 1)", // 金黄 #FFD700 "rgba(255, 127, 0, 1)", // 橙 #FF7F00 "rgba(255, 0, 0, 1)", // 红 #FF0000 ], }, ]; // 预设分类方法 const CLASSIFICATION_METHODS = [ { name: "优雅分段", value: "pretty_breaks" }, // 浏览器中实现Jenks算法性能较差,暂时移除 // { name: "自然间断", value: "jenks_optimized" }, ]; const StyleEditorPanel: React.FC = ({ layerStyleStates, setLayerStyleStates, }) => { const map = useMap(); const data = useData(); if (!data) { return
Loading...
; // 或其他占位符 } const { currentJunctionCalData, currentPipeCalData, junctionText, pipeText, setShowJunctionText, setShowPipeText, setJunctionText, setPipeText, } = data; const { open, close } = useNotification(); const [applyJunctionStyle, setApplyJunctionStyle] = useState(false); const [applyPipeStyle, setApplyPipeStyle] = useState(false); const [styleUpdateTrigger, setStyleUpdateTrigger] = useState(0); // 用于触发样式更新的状态 const prevStyleUpdateTriggerRef = useRef(0); const [renderLayers, setRenderLayers] = useState([]); const [selectedRenderLayer, setSelectedRenderLayer] = useState(); const [availableProperties, setAvailableProperties] = useState< { name: string; value: string }[] >([]); const [styleConfig, setStyleConfig] = useState({ property: "", classificationMethod: "pretty_breaks", segments: 5, minSize: 4, maxSize: 12, minStrokeWidth: 2, maxStrokeWidth: 6, fixedStrokeWidth: 3, colorType: "single", startColor: "rgba(51, 153, 204, 0.9)", endColor: "rgba(204, 51, 51, 0.9)", showLabels: false, opacity: 0.9, adjustWidthByProperty: true, }); // 颜色方案选择 const [singlePaletteIndex, setSinglePaletteIndex] = useState(0); const [gradientPaletteIndex, setGradientPaletteIndex] = useState(0); const [rainbowPaletteIndex, setRainbowPaletteIndex] = useState(0); // 根据分段数生成相应数量的渐进颜色 const generateGradientColors = useCallback( (segments: number): string[] => { const { start, end } = GRADIENT_PALETTES[gradientPaletteIndex]; const colors: string[] = []; const startColor = parseColor(start); const endColor = parseColor(end); for (let i = 0; i < segments; i++) { const ratio = i / (segments - 1); const r = Math.round( startColor.r + (endColor.r - startColor.r) * ratio ); const g = Math.round( startColor.g + (endColor.g - startColor.g) * ratio ); const b = Math.round( startColor.b + (endColor.b - startColor.b) * ratio ); colors.push(`rgba(${r}, ${g}, ${b}, 1)`); } return colors; }, [gradientPaletteIndex, parseColor] ); // 根据分段数生成彩虹色 const generateRainbowColors = useCallback( (segments: number): string[] => { const baseColors = RAINBOW_PALETTES[rainbowPaletteIndex].colors; if (segments <= baseColors.length) { // 如果分段数小于等于基础颜色数,均匀选取 const step = baseColors.length / segments; return Array.from( { length: segments }, (_, i) => baseColors[Math.floor(i * step)] ); } else { // 如果分段数大于基础颜色数,重复使用 return Array.from( { length: segments }, (_, i) => baseColors[i % baseColors.length] ); } }, [rainbowPaletteIndex] ); // 保存当前图层的样式状态 const saveLayerStyle = useCallback( (layerId?: string, newLegendConfig?: LegendStyleConfig) => { if (!selectedRenderLayer || !styleConfig.property) { console.warn("无法保存样式:缺少必要的图层或样式配置"); return; } if (!layerId) return; // 如果没有传入 layerId,则不保存 // 如果没有传入图例配置,则创建一个默认的空配置 const layerName = newLegendConfig?.layerName || selectedRenderLayer.get("name") || `图层${layerId}`; const property = availableProperties.find( (p) => p.value === styleConfig.property ); let legendConfig: LegendStyleConfig = newLegendConfig || { layerId, layerName, property: property?.name || styleConfig.property, colors: [], type: selectedRenderLayer.get("type"), dimensions: [], breaks: [], }; const newStyleState: LayerStyleState = { layerId, layerName, styleConfig: { ...styleConfig }, legendConfig: { ...legendConfig }, isActive: true, }; setLayerStyleStates((prev) => { // 检查是否已存在该图层的样式状态 const existingIndex = prev.findIndex( (state) => state.layerId === layerId ); if (existingIndex !== -1) { // 更新已存在的状态 const updated = [...prev]; updated[existingIndex] = newStyleState; return updated; } else { // 添加新的状态 return [...prev, newStyleState]; } }); }, [selectedRenderLayer, styleConfig] ); // 设置分类样式参数,触发样式应用 const setStyleState = () => { if (!selectedRenderLayer) return; const layerId = selectedRenderLayer.get("value"); const property = styleConfig.property; if (layerId !== undefined && property !== undefined) { // 更新文字标签设置 if (layerId === "junctions") { if (setJunctionText && setShowJunctionText) { setJunctionText(property); setShowJunctionText(styleConfig.showLabels); setApplyJunctionStyle(true); saveLayerStyle(layerId); open?.({ type: "success", message: "节点图层样式设置成功,等待数据更新。", }); } } if (layerId === "pipes") { if (setPipeText && setShowPipeText) { setPipeText(property); setShowPipeText(styleConfig.showLabels); setApplyPipeStyle(true); saveLayerStyle(layerId); open?.({ type: "success", message: "管道图层样式设置成功,等待数据更新。", }); } } // 触发样式更新 setStyleUpdateTrigger((prev) => prev + 1); } }; // 计算分类样式,并应用到对应图层 const applyClassificationStyle = ( layerType: "junctions" | "pipes", styleConfig: any ) => { if ( layerType === "junctions" && currentJunctionCalData && currentJunctionCalData.length > 0 ) { // 应用节点样式 let junctionStyleConfigState = layerStyleStates.find( (s) => s.layerId === "junctions" ); // 更新节点数据属性 const segments = junctionStyleConfigState?.styleConfig.segments ?? 5; const breaks = calculateClassification( currentJunctionCalData.map((d) => d.value), segments, styleConfig.classificationMethod ); if (breaks.length === 0) { console.warn("计算的 breaks 为空,无法应用样式"); return; } if (junctionStyleConfigState) applyLayerStyle(junctionStyleConfigState, breaks); } else if ( layerType === "pipes" && currentPipeCalData && currentPipeCalData.length > 0 ) { // 应用管道样式 let pipeStyleConfigState = layerStyleStates.find( (s) => s.layerId === "pipes" ); // 更新管道数据属性 const segments = pipeStyleConfigState?.styleConfig.segments ?? 5; const breaks = calculateClassification( currentPipeCalData.map((d) => d.value), segments, styleConfig.classificationMethod ); if (pipeStyleConfigState) applyLayerStyle(pipeStyleConfigState, breaks); } }; // 应用样式函数,传入 breaks 数据 const applyLayerStyle = ( layerStyleConfig: LayerStyleState, breaks?: number[] ) => { // 使用传入的 breaks 数据 if (!breaks || breaks.length === 0) { console.warn("没有有效的 breaks 数据"); return; } const styleConfig = layerStyleConfig.styleConfig; const renderLayer = renderLayers.filter((layer) => { return layer.get("value") === layerStyleConfig.layerId; })[0]; if (!renderLayer || !styleConfig?.property) return; const layerType: string = renderLayer?.get("type"); const source = renderLayer.getSource(); if (!source) return; const breaksLength = breaks.length; // 根据 breaks 计算每个分段的颜色,线条粗细 const colors: string[] = styleConfig.colorType === "single" ? // 单一色重复多次 Array.from({ length: breaksLength }, () => { return SINGLE_COLOR_PALETTES[singlePaletteIndex].color; }) : styleConfig.colorType === "gradient" ? generateGradientColors(breaksLength) : generateRainbowColors(breaksLength); // 计算每个分段的线条粗细和点大小 const dimensions: number[] = layerType === "linestring" ? styleConfig.adjustWidthByProperty ? Array.from({ length: breaksLength }, (_, i) => { const ratio = i / (breaksLength - 1); return ( styleConfig.minStrokeWidth + (styleConfig.maxStrokeWidth - styleConfig.minStrokeWidth) * ratio ); }) : Array.from( { length: breaksLength }, () => styleConfig.fixedStrokeWidth ) // 使用固定宽度 : Array.from({ length: breaksLength }, (_, i) => { const ratio = i / (breaksLength - 1); return ( styleConfig.minSize + (styleConfig.maxSize - styleConfig.minSize) * ratio ); }); // 动态生成颜色条件表达式 const generateColorConditions = (property: string): any[] => { const conditions: any[] = ["case"]; for (let i = 0; i < breaks.length; i++) { // 添加条件:属性值 <= 当前断点 conditions.push(["<=", ["get", property], breaks[i]]); // 添加对应的颜色值 const colorObj = parseColor(colors[i]); const color = `rgba(${colorObj.r}, ${colorObj.g}, ${colorObj.b}, ${styleConfig.opacity})`; conditions.push(color); } const colorObj = parseColor(colors[colors.length - 1]); const color = `rgba(${colorObj.r}, ${colorObj.g}, ${colorObj.b}, ${styleConfig.opacity})`; // 添加默认值(最后一个颜色) conditions.push(color); return conditions; }; // 动态生成尺寸条件表达式 const generateDimensionConditions = (property: string): any[] => { const conditions: any[] = ["case"]; for (let i = 0; i < breaks.length; i++) { conditions.push(["<=", ["get", property], breaks[i]]); conditions.push(dimensions[i]); } conditions.push(dimensions[dimensions.length - 1]); return conditions; }; const generateDimensionPointConditions = (property: string): any[] => { const conditions: any[] = ["case"]; for (let i = 0; i < breaks.length; i++) { conditions.push(["<=", ["get", property], breaks[i]]); conditions.push([ "interpolate", ["linear"], ["zoom"], 12, 1, // 使用配置的最小尺寸 24, dimensions[i], ]); } conditions.push(dimensions[dimensions.length - 1]); return conditions; }; // 创建基于 breaks 的动态 FlatStyle const dynamicStyle: FlatStyleLike = {}; // 根据图层类型设置不同的样式属性 if (layerType === "linestring") { dynamicStyle["stroke-color"] = generateColorConditions( styleConfig.property ); dynamicStyle["stroke-width"] = generateDimensionConditions( styleConfig.property ); } else if (layerType === "point") { dynamicStyle["circle-fill-color"] = generateColorConditions( styleConfig.property ); dynamicStyle["circle-radius"] = generateDimensionPointConditions( styleConfig.property ); dynamicStyle["circle-stroke-color"] = generateColorConditions( styleConfig.property ); dynamicStyle["circle-stroke-width"] = 2; } renderLayer.setStyle(dynamicStyle); // 用初始化时的样式配置更新图例配置,避免覆盖已有的图例名称和属性 const layerId = renderLayer.get("value"); const initLayerStyleState = layerStyleStates.find( (s) => s.layerId === layerId ); // 创建图例配置对象 const legendConfig: LegendStyleConfig = { layerName: initLayerStyleState?.layerName || `图层${layerId}`, layerId: layerId, property: initLayerStyleState?.legendConfig.property || "", colors: colors, type: layerType, dimensions: dimensions, breaks: breaks, }; // 自动保存样式状态,直接传入图例配置 setTimeout(() => { saveLayerStyle(renderLayer.get("value"), legendConfig); }, 100); }; // 重置样式 const resetStyle = useCallback(() => { if (!selectedRenderLayer) return; // 重置 WebGL 图层样式 const defaultFlatStyle: FlatStyleLike = config.MAP_DEFAULT_STYLE; selectedRenderLayer.setStyle(defaultFlatStyle); // 删除对应图层的样式状态,从而移除图例显示 const layerId = selectedRenderLayer.get("value"); if (layerId !== undefined) { setLayerStyleStates((prev) => prev.filter((state) => state.layerId !== layerId) ); // 重置样式应用状态 if (layerId === "junctions") { setApplyJunctionStyle(false); if (setShowJunctionText) setShowJunctionText(false); if (setJunctionText) setJunctionText(""); } else if (layerId === "pipes") { setApplyPipeStyle(false); if (setShowPipeText) setShowPipeText(false); if (setPipeText) setPipeText(""); } } }, [selectedRenderLayer]); // 更新当前 VectorTileSource 中的所有缓冲要素属性 const updateVectorTileSource = (property: string, data: any[]) => { if (!map) return; const vectorTileSources = map .getAllLayers() .filter((layer) => layer instanceof WebGLVectorTileLayer) .map((layer) => layer.getSource() as VectorTileSource) .filter((source) => source); if (!vectorTileSources.length) return; // 创建 id 到 value 的映射 const dataMap = new Map(); data.forEach((d: any) => { dataMap.set(d.ID, d.value || 0); }); // 直接遍历所有瓦片和要素,无需分批处理 vectorTileSources.forEach((vectorTileSource) => { const sourceTiles = vectorTileSource.sourceTiles_; Object.values(sourceTiles).forEach((vectorTile) => { const renderFeatures = vectorTile.getFeatures(); if (!renderFeatures || renderFeatures.length === 0) return; // 直接更新要素属性 renderFeatures.forEach((renderFeature) => { const featureId = renderFeature.get("id"); const value = dataMap.get(featureId); if (value !== undefined) { (renderFeature as any).properties_[property] = value; } }); }); }); }; // 新增事件,监听 VectorTileSource 的 tileloadend 事件,为新增瓦片数据动态更新要素属性 const [tileLoadListeners, setTileLoadListeners] = useState< Map void> >(new Map()); const attachVectorTileSourceLoadedEvent = ( layerId: string, property: string, data: any[] ) => { if (!map) return; const vectorTileSource = map .getAllLayers() .filter((layer) => layer.get("value") === layerId) .map((layer) => layer.getSource() as VectorTileSource) .filter((source) => source)[0]; if (!vectorTileSource) return; // 创建 id 到 value 的映射 const dataMap = new Map(); data.forEach((d: any) => { dataMap.set(d.ID, d.value || 0); }); // 新增监听器并保存 const newListeners = new Map void>(); const listener = (event: any) => { try { if (event.tile instanceof VectorTile) { const renderFeatures = event.tile.getFeatures(); if (!renderFeatures || renderFeatures.length === 0) return; // 直接更新要素属性 renderFeatures.forEach((renderFeature: any) => { const featureId = renderFeature.get("id"); const value = dataMap.get(featureId); if (value !== undefined) { (renderFeature as any).properties_[property] = value; } }); } } catch (error) { console.error("Error processing tile load event:", error); } }; vectorTileSource.on("tileloadend", listener); newListeners.set(vectorTileSource, listener); setTileLoadListeners(newListeners); }; // 新增函数:取消对应 layerId 已添加的 on 事件 const removeVectorTileSourceLoadedEvent = (layerId: string) => { if (!map) return; const vectorTileSource = map .getAllLayers() .filter((layer) => layer.get("value") === layerId) .map((layer) => layer.getSource() as VectorTileSource) .filter((source) => source)[0]; if (!vectorTileSource) return; const listener = tileLoadListeners.get(vectorTileSource); if (listener) { vectorTileSource.un("tileloadend", listener); setTileLoadListeners((prev) => { const newMap = new Map(prev); newMap.delete(vectorTileSource); return newMap; }); } }; // 监听数据变化,重新应用样式。由样式应用按钮触发,或由数据变化触发 useEffect(() => { // 判断此次触发是否由用户点击“应用”按钮引起 const isUserTrigger = styleUpdateTrigger !== prevStyleUpdateTriggerRef.current; // 更新 prevStyleUpdateTriggerRef prevStyleUpdateTriggerRef.current = styleUpdateTrigger; const updateJunctionStyle = () => { if (!currentJunctionCalData) return; const junctionStyleConfigState = layerStyleStates.find( (s) => s.layerId === "junctions" ); applyClassificationStyle( "junctions", junctionStyleConfigState?.styleConfig ); // 更新现有的 VectorTileSource updateVectorTileSource(junctionText, currentJunctionCalData); // 移除旧的监听器,并添加新的监听器 removeVectorTileSourceLoadedEvent("junctions"); attachVectorTileSourceLoadedEvent( "junctions", junctionText, currentJunctionCalData ); }; const updatePipeStyle = () => { if (!currentPipeCalData) return; const pipeStyleConfigState = layerStyleStates.find( (s) => s.layerId === "pipes" ); applyClassificationStyle("pipes", pipeStyleConfigState?.styleConfig); // 更新现有的 VectorTileSource updateVectorTileSource(pipeText, currentPipeCalData); // 移除旧的监听器,并添加新的监听器 removeVectorTileSourceLoadedEvent("pipes"); attachVectorTileSourceLoadedEvent("pipes", pipeText, currentPipeCalData); }; if (isUserTrigger) { if (selectedRenderLayer?.get("value") === "junctions") { updateJunctionStyle(); } else if (selectedRenderLayer?.get("value") === "pipes") { updatePipeStyle(); } return; } if ( applyJunctionStyle && currentJunctionCalData && currentJunctionCalData.length > 0 ) { updateJunctionStyle(); } if (applyPipeStyle && currentPipeCalData && currentPipeCalData.length > 0) { updatePipeStyle(); } if (!applyJunctionStyle) { removeVectorTileSourceLoadedEvent("junctions"); } if (!applyPipeStyle) { removeVectorTileSourceLoadedEvent("pipes"); } }, [ styleUpdateTrigger, applyJunctionStyle, applyPipeStyle, currentJunctionCalData, currentPipeCalData, ]); // 获取地图中的矢量图层,用于选择图层选项 useEffect(() => { if (!map) return; const updateVisibleLayers = () => { const layers = map.getAllLayers(); // 筛选矢量瓦片图层 const webGLVectorTileLayers = layers.filter( (layer) => layer.get("value") === "junctions" || layer.get("value") === "pipes" // 暂时只处理这两个图层 ) as WebGLVectorTileLayer[]; setRenderLayers(webGLVectorTileLayers); }; updateVisibleLayers(); }, [map]); // 获取选中图层的属性,并检查是否有已缓存的样式状态 useEffect(() => { // 如果没有矢量图层或没有选中图层,清空属性列表 if (!renderLayers || renderLayers.length === 0) { setAvailableProperties([]); return; } // 如果没有选中图层,清空属性列表 if (!selectedRenderLayer) { setAvailableProperties([]); return; } // 获取第一个要素的数值型属性 const properties = selectedRenderLayer.get("properties") || {}; setAvailableProperties(properties); // 设置选中的渲染图层 const renderLayer = renderLayers.filter((layer) => { return layer.get("value") === selectedRenderLayer?.get("value"); })[0]; setSelectedRenderLayer(renderLayer); // 检查是否有已缓存的样式状态,如果有则自动恢复 const layerId = selectedRenderLayer.get("value"); const cachedStyleState = layerStyleStates.find( (state) => state.layerId === layerId ); if (cachedStyleState) { setStyleConfig(cachedStyleState.styleConfig); } }, [renderLayers, selectedRenderLayer, map, renderLayers, layerStyleStates]); // 监听颜色类型变化,当切换到单一色时自动勾选宽度调整选项 useEffect(() => { if (styleConfig.colorType === "single") { setStyleConfig((prev) => ({ ...prev, adjustWidthByProperty: true, })); } }, [styleConfig.colorType]); const getColorSetting = () => { if (styleConfig.colorType === "single") { return ( 单一色方案 ); } if (styleConfig.colorType === "gradient") { return ( 渐进色方案 ); } if (styleConfig.colorType === "rainbow") { return ( 离散彩虹方案 ); } }; // 根据不同图层的类型和颜色分类方案显示不同的大小设置 const getSizeSetting = () => { let colors: string[] = []; if (styleConfig.colorType === "single") { const color = SINGLE_COLOR_PALETTES[singlePaletteIndex].color; colors = [color, color]; } else if (styleConfig.colorType === "gradient") { const { start, end } = GRADIENT_PALETTES[gradientPaletteIndex]; colors = [start, end]; } else if (styleConfig.colorType === "rainbow") { const rainbowColors = RAINBOW_PALETTES[rainbowPaletteIndex].colors; colors = [rainbowColors[0], rainbowColors[rainbowColors.length - 1]]; } if (selectedRenderLayer?.get("type") === "point") { return ( 点大小范围: {styleConfig.minSize} - {styleConfig.maxSize} 像素 最小值 setStyleConfig((prev) => ({ ...prev, minSize: value as number, })) } min={2} max={8} step={1} size="small" /> 最大值 setStyleConfig((prev) => ({ ...prev, maxSize: value as number, })) } min={10} max={16} step={1} size="small" /> {/* 点大小预览 */} 预览: ); } if (selectedRenderLayer?.get("type") === "linestring") { return ( {/* 勾选项:是否根据属性调整线条宽度 */} setStyleConfig((prev) => ({ ...prev, adjustWidthByProperty: e.target.checked, })) } disabled={styleConfig.colorType === "single"} /> } label="根据数值分段调整线条宽度" /> {styleConfig.adjustWidthByProperty && ( <> 线条宽度范围: {styleConfig.minStrokeWidth} -{" "} {styleConfig.maxStrokeWidth}px 最小值 setStyleConfig((prev) => ({ ...prev, minStrokeWidth: value as number, })) } min={1} max={4} step={0.5} size="small" /> 最大值 setStyleConfig((prev) => ({ ...prev, maxStrokeWidth: value as number, })) } min={6} max={12} step={0.5} size="small" /> {/* 线条宽度预览 */} 预览: )} {!styleConfig.adjustWidthByProperty && ( <> 固定线条宽度: {styleConfig.fixedStrokeWidth}px setStyleConfig((prev) => ({ ...prev, fixedStrokeWidth: value as number, })) } min={1} max={10} step={0.5} size="small" /> {/* 固定宽度预览 */} 预览: )} ); } }; return ( <>
{/* 图层选择 */} 选择图层 {/* 属性选择 */} 分级属性 {/* 分类选择 */} 分类方法 {/* 分类数量 */} 分类数量: {styleConfig.segments} setStyleConfig((prev) => ({ ...prev, segments: value as number })) } min={3} max={10} step={1} marks size="small" /> {/* 颜色方案 */} 颜色方案 {getColorSetting()} {/* 大小设置 */} {getSizeSetting()} {/* 透明度设置 */} 透明度: {(styleConfig.opacity * 100).toFixed(0)}% setStyleConfig((prev) => ({ ...prev, opacity: value as number, })) } min={0.1} max={1} step={0.05} size="small" /> {/* 是否显示属性文字 */} setStyleConfig((prev) => ({ ...prev, showLabels: e.target.checked, })) } /> } label="显示属性(放大后显示)" />
{/* 操作按钮 */}
); }; export default StyleEditorPanel;