From b261ef0573214c310c8adff59933da54baa8b366 Mon Sep 17 00:00:00 2001 From: monitor1394 Date: Sun, 12 Sep 2021 15:01:40 +0800 Subject: [PATCH] improve radar chart --- Assets/XCharts/CHANGELOG-EN.md | 1 + Assets/XCharts/CHANGELOG.md | 1 + .../Documentation/XCharts配置项手册.md | 4 ++ .../Documentation/xcharts-configuration-EN.md | 6 +- .../Editor/PropertyDrawers/RadarDrawer.cs | 4 ++ .../XCharts/Runtime/Component/Main/Radar.cs | 55 +++++++++++++++++++ .../XCharts/Runtime/Component/Sub/MarkLine.cs | 2 +- .../Runtime/Internal/DrawSerieRadar.cs | 29 ++++++++-- .../Runtime/Internal/Utility/ChartDrawer.cs | 30 +++++++--- Assets/XCharts/Runtime/XUGL/UGL.cs | 16 +++++- 10 files changed, 132 insertions(+), 16 deletions(-) diff --git a/Assets/XCharts/CHANGELOG-EN.md b/Assets/XCharts/CHANGELOG-EN.md index a3623d34..c09828b5 100644 --- a/Assets/XCharts/CHANGELOG-EN.md +++ b/Assets/XCharts/CHANGELOG-EN.md @@ -40,6 +40,7 @@ ## master +* (2021.09.08) Improved `RadarChart` * (2021.09.07) Fixed bug where `label` does not disappear at the end of `PieChart` fade animation #168 * (2021.09.06) Fixed bug where `GaugeChart` changing `splitNumber` with code does not refresh `label` #167 diff --git a/Assets/XCharts/CHANGELOG.md b/Assets/XCharts/CHANGELOG.md index 9099a172..323f1d57 100644 --- a/Assets/XCharts/CHANGELOG.md +++ b/Assets/XCharts/CHANGELOG.md @@ -40,6 +40,7 @@ ## master +* (2021.09.08) 完善`RadarChart` * (2021.09.07) 修复`PieChart`渐出动画结束时`label`没有消失的问题 #168 * (2021.09.06) 修复`GaugeChart`用代码改变`splitNumber`不会刷新`label`的问题 #167 diff --git a/Assets/XCharts/Documentation/XCharts配置项手册.md b/Assets/XCharts/Documentation/XCharts配置项手册.md index b2161ea7..151d84c2 100644 --- a/Assets/XCharts/Documentation/XCharts配置项手册.md +++ b/Assets/XCharts/Documentation/XCharts配置项手册.md @@ -176,6 +176,9 @@ * `ceilRate`:最大最小值向上取整的倍率。默认为0时自动计算。 * `splitNumber`:分割段数。默认为 `5`。 * `isAxisTooltip`:是否Tooltip显示轴线上的所有数据。只对Mutiple类型的Radar有效。 +* `outRangeColor`:数值超出范围时显示的颜色。 +* `connectCenter`:数值是否连线到中心点。 +* `lineGradient`:数值线段是否渐变。 * `splitLine`:分割线条 [AxisSplitLine](#AxisSplitLine)。 * `splitArea`:分割区域 [AxisSplitArea](#AxisSplitArea)。 * `indicator`:是否显示指示器。 @@ -187,6 +190,7 @@ * `name`:指示器名称。 * `max`:指示器的最大值,默认为 0 无限制。 * `min`:指示器的最小值,默认为 0 无限制。 +* `range`:指示器的正常值范围,当数值超出这个范围时显示`Radar`的`outRangeColor`颜色。 * `textStyle`:文本样式 [TextStyle](#TextStyle)。 ## `TextLimit` diff --git a/Assets/XCharts/Documentation/xcharts-configuration-EN.md b/Assets/XCharts/Documentation/xcharts-configuration-EN.md index bc8dd542..7a6f6d70 100644 --- a/Assets/XCharts/Documentation/xcharts-configuration-EN.md +++ b/Assets/XCharts/Documentation/xcharts-configuration-EN.md @@ -176,7 +176,10 @@ Radar coordinate conponnet for radar charts. * `center`: the center of radar chart. The `center[0]` is the x-coordinate, and the `center[1]` is the y-coordinate. When value between 0 and 1 represents a percentage relative to the chart.[default:[0.5f,0.4f]]. * `ceilRate`: The ratio of maximum and minimum values rounded upward. The default is 0, which is automatically calculated.[default:0]. * `splitNumber`: Segments of indicator axis.[default:5]. -* `splitNumber`: Tooltip displays all the data on the axis.[default:false]. +* `isAxisTooltip`: Tooltip displays all the data on the axis.[default:false]. +* `outRangeColor`: The color displayed when data out of range.[default:red] +* `connectCenter`: Whether serie data connect to radar center with line.[default:false] +* `lineGradient`: Whether need gradient for data line..[default:true] * `splitLine`: The split line style of radar [AxisSplitLine](#AxisSplitLine). * `splitArea`: The split area style of radar [AxisSplitArea](#AxisSplitArea). * `indicator`: Whether to show indicator. @@ -190,6 +193,7 @@ Indicator of radar chart, which is used to assign multiple variables(dimensions) * `name`: The name of indicator. * `max`: The maximum value of indicator, with default value of 0, but we recommend to set it manually. * `min`: The minimum value of indicator, with default value of 0. +* `min`: Normal range. When the value is outside this range, the display color is automatically changed. * `textStyle`: The text style of indicator [TextStyle](#TextStyle). ## `TextLimit` diff --git a/Assets/XCharts/Editor/PropertyDrawers/RadarDrawer.cs b/Assets/XCharts/Editor/PropertyDrawers/RadarDrawer.cs index a3dc5493..efd85106 100644 --- a/Assets/XCharts/Editor/PropertyDrawers/RadarDrawer.cs +++ b/Assets/XCharts/Editor/PropertyDrawers/RadarDrawer.cs @@ -28,6 +28,9 @@ namespace XCharts PropertyField(prop, "m_SplitNumber"); PropertyField(prop, "m_CeilRate"); PropertyField(prop, "m_IsAxisTooltip"); + PropertyField(prop, "m_OutRangeColor"); + PropertyField(prop, "m_ConnectCenter"); + PropertyField(prop, "m_LineGradient"); PropertyField(prop, "m_AxisLine"); PropertyField(prop, "m_SplitLine"); PropertyField(prop, "m_SplitArea"); @@ -50,6 +53,7 @@ namespace XCharts PropertyField(prop, "m_Name"); PropertyField(prop, "m_Min"); PropertyField(prop, "m_Max"); + PropertyTwoFiled(prop, "m_Range"); PropertyField(prop, "m_TextStyle"); --EditorGUI.indentLevel; } diff --git a/Assets/XCharts/Runtime/Component/Main/Radar.cs b/Assets/XCharts/Runtime/Component/Main/Radar.cs index f4816e4b..23badc49 100644 --- a/Assets/XCharts/Runtime/Component/Main/Radar.cs +++ b/Assets/XCharts/Runtime/Component/Main/Radar.cs @@ -56,6 +56,7 @@ namespace XCharts [SerializeField] private string m_Name; [SerializeField] private double m_Max; [SerializeField] private double m_Min; + [SerializeField] private double[] m_Range = new double[2] { 0, 0 }; [SerializeField] private TextStyle m_TextStyle = new TextStyle(); /// @@ -83,6 +84,24 @@ namespace XCharts /// 指示器的文本组件。 /// public Text text { get; set; } + /// + /// Normal range. When the value is outside this range, the display color is automatically changed. + /// 正常值范围。当数值不在这个范围时,会自动变更显示颜色。 + /// + public double[] range + { + get { return m_Range; } + set { if (value != null && value.Length == 2) { m_Range = value; } } + } + + public bool IsInRange(double value) + { + if (m_Range == null || m_Range.Length < 2) return true; + if (m_Range[0] != 0 || m_Range[1] != 0) + return value >= m_Range[0] && value <= m_Range[1]; + else + return true; + } } [SerializeField] private bool m_Show; [SerializeField] private Shape m_Shape; @@ -97,6 +116,9 @@ namespace XCharts [SerializeField] private float m_IndicatorGap = 10; [SerializeField] private int m_CeilRate = 0; [SerializeField] private bool m_IsAxisTooltip; + [SerializeField] private Color32 m_OutRangeColor = Color.red; + [SerializeField] private bool m_ConnectCenter = false; + [SerializeField] private bool m_LineGradient = true; [SerializeField] private List m_IndicatorList = new List(); /// /// [default:true] @@ -214,6 +236,33 @@ namespace XCharts set { if (PropertyUtil.SetStruct(ref m_PositionType, value)) SetAllDirty(); } } /// + /// The color displayed when data out of range. + /// 数值超出范围时显示的颜色。 + /// + public Color32 outRangeColor + { + get { return m_OutRangeColor; } + set { if (PropertyUtil.SetStruct(ref m_OutRangeColor, value)) SetAllDirty(); } + } + /// + /// Whether serie data connect to radar center with line. + /// 数值是否连线到中心点。 + /// + public bool connectCenter + { + get { return m_ConnectCenter; } + set { if (PropertyUtil.SetStruct(ref m_ConnectCenter, value)) SetAllDirty(); } + } + /// + /// Whether need gradient for data line. + /// 数值线段是否需要渐变。 + /// + public bool lineGradient + { + get { return m_LineGradient; } + set { if (PropertyUtil.SetStruct(ref m_LineGradient, value)) SetAllDirty(); } + } + /// /// the indicator list. /// 指示器列表。 /// @@ -276,6 +325,12 @@ namespace XCharts return true; } + public bool IsInIndicatorRange(int index, double value) + { + var indicator = GetIndicator(index); + return indicator == null ? true : indicator.IsInRange(value); + } + public double GetIndicatorMin(int index) { if (index >= 0 && index < m_IndicatorList.Count) diff --git a/Assets/XCharts/Runtime/Component/Sub/MarkLine.cs b/Assets/XCharts/Runtime/Component/Sub/MarkLine.cs index 61f3dd82..f0f6abac 100644 --- a/Assets/XCharts/Runtime/Component/Sub/MarkLine.cs +++ b/Assets/XCharts/Runtime/Component/Sub/MarkLine.cs @@ -520,7 +520,7 @@ namespace XCharts var theme = chart.theme.axis; var lineColor = ChartHelper.IsClearColor(data.lineStyle.color) ? serieColor : data.lineStyle.color; var lineWidth = data.lineStyle.width == 0 ? theme.lineWidth : data.lineStyle.width; - ChartDrawer.DrawLineStyle(vh, data.lineStyle, sp, ep, lineColor, lineWidth, LineStyle.Type.Dashed); + ChartDrawer.DrawLineStyle(vh, data.lineStyle, sp, ep, lineWidth, LineStyle.Type.Dashed, lineColor, lineColor); if (data.startSymbol != null && data.startSymbol.show) { DrawMarkLineSymbol(vh, data.startSymbol, serie, grid, chart.theme, sp, sp, lineColor); diff --git a/Assets/XCharts/Runtime/Internal/DrawSerieRadar.cs b/Assets/XCharts/Runtime/Internal/DrawSerieRadar.cs index bc607be6..595e2b1a 100644 --- a/Assets/XCharts/Runtime/Internal/DrawSerieRadar.cs +++ b/Assets/XCharts/Runtime/Internal/DrawSerieRadar.cs @@ -439,6 +439,8 @@ namespace XCharts var startPoint = Vector3.zero; var toPoint = Vector3.zero; var firstPoint = Vector3.zero; + var lastColor = ColorUtil.clearColor32; + var firstColor = ColorUtil.clearColor32; var radar = chart.radars[serie.radarIndex]; var indicatorNum = radar.indicatorList.Count; @@ -503,8 +505,10 @@ namespace XCharts var value = serieData.GetCurrData(1, dataChangeDuration); if (serieData.IsDataChanged()) dataChanging = true; if (max == 0) - { max = serie.runtimeDataMax; + if (!radar.IsInIndicatorRange(j, serieData.GetData(1))) + { + lineColor = radar.outRangeColor; } var radius = (float)(max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max : radar.runtimeDataRadius * value / max); @@ -515,6 +519,8 @@ namespace XCharts startPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle), p.y + radius * Mathf.Cos(currAngle)); firstPoint = startPoint; + lastColor = lineColor; + firstColor = lineColor; } else { @@ -526,22 +532,28 @@ namespace XCharts } if (serie.lineStyle.show) { - ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, toPoint, lineColor, - chart.theme.serie.lineWidth, LineStyle.Type.Solid); + if (radar.connectCenter) + ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, centerPos, + chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor); + ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, toPoint, chart.theme.serie.lineWidth, + LineStyle.Type.Solid, radar.lineGradient ? lastColor : lineColor, lineColor); } startPoint = toPoint; + lastColor = lineColor; } serieData.labelPosition = startPoint; pointList.Add(startPoint); - if (serie.areaStyle.show && j == endIndex) { UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor); } if (serie.lineStyle.show && j == endIndex) { - ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, firstPoint, lineColor, - chart.theme.serie.lineWidth, LineStyle.Type.Solid); + if (radar.connectCenter) + ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, centerPos, + chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor); + ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, firstPoint, chart.theme.serie.lineWidth, + LineStyle.Type.Solid, lineColor, radar.lineGradient ? firstColor : lineColor); } } if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None) @@ -560,6 +572,11 @@ namespace XCharts var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight); var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight); var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight); + if (!radar.IsInIndicatorRange(j, serieData.GetData(1))) + { + symbolColor = radar.outRangeColor; + symbolToColor = radar.outRangeColor; + } chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, serieData.labelPosition, symbolColor, symbolToColor, serie.symbol.gap, cornerRadius); } diff --git a/Assets/XCharts/Runtime/Internal/Utility/ChartDrawer.cs b/Assets/XCharts/Runtime/Internal/Utility/ChartDrawer.cs index bb06afb2..15750c1f 100644 --- a/Assets/XCharts/Runtime/Internal/Utility/ChartDrawer.cs +++ b/Assets/XCharts/Runtime/Internal/Utility/ChartDrawer.cs @@ -88,29 +88,45 @@ namespace XCharts break; } } - - public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle, - Vector3 startPos, Vector3 endPos, Color32 defaultColor, float themeWidth, LineStyle.Type themeType) + + public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle, Vector3 startPos, Vector3 endPos, + Color32 defaultColor, float themeWidth, LineStyle.Type themeType) { var type = lineStyle.GetType(themeType); var width = lineStyle.GetWidth(themeWidth); var color = lineStyle.GetColor(defaultColor); - DrawLineStyle(vh, type, width, startPos, endPos, color); + DrawLineStyle(vh, type, width, startPos, endPos, color, color); + } + + public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle, Vector3 startPos, Vector3 endPos, + float themeWidth, LineStyle.Type themeType, Color32 defaultColor, Color32 defaultToColor) + { + var type = lineStyle.GetType(themeType); + var width = lineStyle.GetWidth(themeWidth); + var color = lineStyle.GetColor(defaultColor); + var toColor = ChartHelper.IsClearColor(defaultToColor) ? color : defaultToColor; + DrawLineStyle(vh, type, width, startPos, endPos, color, toColor); } public static void DrawLineStyle(VertexHelper vh, LineStyle.Type lineType, float lineWidth, Vector3 startPos, Vector3 endPos, Color32 color) + { + DrawLineStyle(vh, lineType, lineWidth, startPos, endPos, color, color); + } + + public static void DrawLineStyle(VertexHelper vh, LineStyle.Type lineType, float lineWidth, + Vector3 startPos, Vector3 endPos, Color32 color, Color32 toColor) { switch (lineType) { case LineStyle.Type.Dashed: - UGL.DrawDashLine(vh, startPos, endPos, lineWidth, color, color); + UGL.DrawDashLine(vh, startPos, endPos, lineWidth, color, toColor); break; case LineStyle.Type.Dotted: - UGL.DrawDotLine(vh, startPos, endPos, lineWidth, color, color); + UGL.DrawDotLine(vh, startPos, endPos, lineWidth, color, toColor); break; case LineStyle.Type.Solid: - UGL.DrawLine(vh, startPos, endPos, lineWidth, color); + UGL.DrawLine(vh, startPos, endPos, lineWidth, color, toColor); break; case LineStyle.Type.DashDot: UGL.DrawDashDotLine(vh, startPos, endPos, lineWidth, color); diff --git a/Assets/XCharts/Runtime/XUGL/UGL.cs b/Assets/XCharts/Runtime/XUGL/UGL.cs index 5ebc0ed8..492d1e84 100644 --- a/Assets/XCharts/Runtime/XUGL/UGL.cs +++ b/Assets/XCharts/Runtime/XUGL/UGL.cs @@ -55,6 +55,20 @@ namespace XUGL /// 线宽 /// 颜色 public static void DrawLine(VertexHelper vh, Vector3 startPoint, Vector3 endPoint, float width, Color32 color) + { + DrawLine(vh, startPoint, endPoint, width, color, color); + } + + /// + /// Draw a line. 画直线 + /// + /// + /// 起点 + /// 终点 + /// 线宽 + /// 颜色 + /// 渐变颜色 + public static void DrawLine(VertexHelper vh, Vector3 startPoint, Vector3 endPoint, float width, Color32 color, Color32 toColor) { if (startPoint == endPoint) return; Vector3 v = Vector3.Cross(endPoint - startPoint, Vector3.forward).normalized * width; @@ -65,7 +79,7 @@ namespace XUGL for (int j = 0; j < 4; j++) { - s_Vertex[j].color = color; + s_Vertex[j].color = j == 0 || j == 3 ? color : toColor; s_Vertex[j].uv0 = s_ZeroVector2; } vh.AddUIVertexQuad(s_Vertex);