From 1f77461d05bf9372db04603c53083950bf0c1ce9 Mon Sep 17 00:00:00 2001 From: monitor1394 Date: Mon, 10 May 2021 12:45:58 +0800 Subject: [PATCH] =?UTF-8?q?VisualMap=E6=94=AF=E6=8C=81Piecewise=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/PropertyDrawers/VisualMapDrawer.cs | 31 +++++- Runtime/Component/Main/Axis.cs | 1 + Runtime/Component/Main/Settings.cs | 2 +- Runtime/Component/Main/VisualMap.cs | 98 ++++++++++++----- Runtime/Helper/VisualMapHelper.cs | 110 +++++++++++-------- Runtime/Internal/CoordinateChart.cs | 2 +- Runtime/Internal/CoordinateChart_DrawLine.cs | 1 + Runtime/LineChart.cs | 1 - 8 files changed, 165 insertions(+), 81 deletions(-) diff --git a/Editor/PropertyDrawers/VisualMapDrawer.cs b/Editor/PropertyDrawers/VisualMapDrawer.cs index 4c736a5d..f6829d92 100644 --- a/Editor/PropertyDrawers/VisualMapDrawer.cs +++ b/Editor/PropertyDrawers/VisualMapDrawer.cs @@ -21,14 +21,22 @@ namespace XCharts { ++EditorGUI.indentLevel; PropertyField(prop, "m_Type"); - PropertyField(prop, "m_Direction"); PropertyField(prop, "m_AutoMinMax"); PropertyField(prop, "m_Min"); PropertyField(prop, "m_Max"); PropertyField(prop, "m_SplitNumber"); PropertyField(prop, "m_Dimension"); - PropertyListField(prop, "m_InRange"); PropertyListField(prop, "m_OutOfRange"); + var type = (VisualMap.Type)prop.FindPropertyRelative("m_Type").enumValueIndex; + switch (type) + { + case VisualMap.Type.Continuous: + PropertyListField(prop, "m_InRange"); + break; + case VisualMap.Type.Piecewise: + PropertyListField(prop, "m_Pieces"); + break; + } PropertyField(prop, "m_Show"); if (prop.FindPropertyRelative("m_Show").boolValue) { @@ -48,4 +56,23 @@ namespace XCharts } } } + + [CustomPropertyDrawer(typeof(VisualMap.Pieces), true)] + public class PiecesDrawer : BasePropertyDrawer + { + public override string ClassName { get { return "Pieces"; } } + public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label) + { + base.OnGUI(pos, prop, label); + if (MakeFoldout(prop, "")) + { + ++EditorGUI.indentLevel; + PropertyField(prop, "m_Min"); + PropertyField(prop, "m_Max"); + PropertyField(prop, "m_Label"); + PropertyField(prop, "m_Color"); + --EditorGUI.indentLevel; + } + } + } } \ No newline at end of file diff --git a/Runtime/Component/Main/Axis.cs b/Runtime/Component/Main/Axis.cs index 21bd615a..998c79d0 100644 --- a/Runtime/Component/Main/Axis.cs +++ b/Runtime/Component/Main/Axis.cs @@ -414,6 +414,7 @@ namespace XCharts internal bool runtimeLastCheckInverse { get; set; } internal double runtimeMinMaxRange { get { return m_MinMaxValueRange; } set { m_MinMaxValueRange = value; } } internal List runtimeData { get { return m_RuntimeData; } } + public float runtimeScaleWidth { get; internal set; } private int filterStart; private int filterEnd; private int filterMinShow; diff --git a/Runtime/Component/Main/Settings.cs b/Runtime/Component/Main/Settings.cs index f4d05b67..ded79275 100644 --- a/Runtime/Component/Main/Settings.cs +++ b/Runtime/Component/Main/Settings.cs @@ -24,7 +24,7 @@ namespace XCharts [SerializeField] protected Material m_TopPainterMaterial; [SerializeField] [Range(1, 10)] protected float m_LineSmoothStyle = 3f; [SerializeField] [Range(1f, 20)] protected float m_LineSmoothness = 2f; - [SerializeField] [Range(1f, 20)] protected float m_LineSegmentDistance = 3f; + [SerializeField] [Range(0.5f, 20)] protected float m_LineSegmentDistance = 3f; [SerializeField] [Range(1, 10)] protected float m_CicleSmoothness = 2f; [SerializeField] protected float m_LegendIconLineWidth = 2; [SerializeField] private float[] m_LegendIconCornerRadius = new float[] { 0.25f, 0.25f, 0.25f, 0.25f }; diff --git a/Runtime/Component/Main/VisualMap.cs b/Runtime/Component/Main/VisualMap.cs index 1b77a6ec..483616ea 100644 --- a/Runtime/Component/Main/VisualMap.cs +++ b/Runtime/Component/Main/VisualMap.cs @@ -32,25 +32,6 @@ namespace XCharts Piecewise } - /// - /// 方向。X轴还是Y轴。 - /// - public enum Direction - { - /// - /// 默认方向。 - /// - Default, - /// - /// X轴方向。 - /// - X, - /// - /// Y轴方向。 - /// - Y - } - /// /// 选择模式 /// @@ -66,10 +47,42 @@ namespace XCharts Single } + [System.Serializable] + public class Pieces + { + [SerializeField] private float m_Min; + [SerializeField] private float m_Max; + [SerializeField] private string m_Label; + [SerializeField] private Color32 m_Color; + + /// + /// 范围最小值 + /// + public float min { get { return m_Min; } set { m_Min = value; } } + /// + /// 范围最大值 + /// + public float max { get { return m_Max; } set { m_Max = value; } } + /// + /// 文字描述 + /// + public string label { get { return m_Label; } set { m_Label = value; } } + /// + /// 颜色 + /// + public Color32 color { get { return m_Color; } set { m_Color = value; } } + + public bool Contains(float value, float minMaxRange) + { + var cmin = Mathf.Abs(m_Min) < 1 ? minMaxRange * m_Min : m_Min; + var cmax = Mathf.Abs(m_Max) < 1 ? minMaxRange * m_Max : m_Max; + return value >= cmin && value < cmax; + } + } + [SerializeField] private bool m_Enable = false; [SerializeField] private bool m_Show = true; [SerializeField] private Type m_Type = Type.Continuous; - [SerializeField] private Direction m_Direction = Direction.Default; [SerializeField] private SelectedMode m_SelectedMode = SelectedMode.Multiple; [SerializeField] private float m_Min = 0; [SerializeField] private float m_Max = 100f; @@ -89,7 +102,8 @@ namespace XCharts [SerializeField] private Orient m_Orient = Orient.Horizonal; [SerializeField] private Location m_Location = Location.defaultLeft; [SerializeField] private List m_InRange = new List(); - [SerializeField] private List m_OutOfRange = new List(); + [SerializeField] private List m_OutOfRange = new List() { Color.gray }; + [SerializeField] private List m_Pieces = new List(); /// /// Whether enable visualMap component. @@ -125,14 +139,6 @@ namespace XCharts set { if (PropertyUtil.SetStruct(ref m_Type, value)) SetVerticesDirty(); } } /// - /// 映射方向。 - /// - public Direction direction - { - get { return m_Direction; } - set { if (PropertyUtil.SetStruct(ref m_Direction, value)) SetVerticesDirty(); } - } - /// /// the selected mode for Piecewise visualMap. /// 选择模式。 /// @@ -311,6 +317,14 @@ namespace XCharts get { return m_OutOfRange; } set { if (value != null) { m_OutOfRange = value; SetVerticesDirty(); } } } + /// + /// 分段式每一段的相关配置。 + /// + public List pieces + { + get { return m_Pieces; } + set { if (value != null) { m_Pieces = value; SetVerticesDirty(); } } + } public override bool vertsDirty { get { return m_VertsDirty || location.anyDirty; } } internal override void ClearVerticesDirty() @@ -423,6 +437,32 @@ namespace XCharts } public Color32 GetColor(float value) + { + switch (type) + { + case Type.Continuous: + return GetContinuousColor(value); + case Type.Piecewise: + return GetPiecesColor(value); + default: + return ColorUtil.clearColor32; + } + } + + private Color32 GetPiecesColor(float value) + { + foreach (var piece in m_Pieces) + { + if (piece.Contains(value, max - min)) + { + return piece.color; + } + } + if (m_OutOfRange.Count > 0) return m_OutOfRange[0]; + else return ChartConst.clearColor32; + } + + private Color32 GetContinuousColor(float value) { if (value < m_Min || value > m_Max) { diff --git a/Runtime/Helper/VisualMapHelper.cs b/Runtime/Helper/VisualMapHelper.cs index f219d3b7..4527e9cc 100644 --- a/Runtime/Helper/VisualMapHelper.cs +++ b/Runtime/Helper/VisualMapHelper.cs @@ -17,19 +17,17 @@ namespace XCharts if (!IsNeedGradient(visualMap) || !visualMap.autoMinMax) return; float min = 0; float max = 0; - switch (visualMap.direction) + if (visualMap.dimension == 0) { - case VisualMap.Direction.Default: - case VisualMap.Direction.X: - min = xAxis.IsCategory() ? 0 : xAxis.runtimeMinValue; - max = xAxis.IsCategory() ? serie.dataCount : xAxis.runtimeMaxValue; - SetMinMax(visualMap, min, max); - break; - case VisualMap.Direction.Y: - min = yAxis.IsCategory() ? 0 : yAxis.runtimeMinValue; - max = yAxis.IsCategory() ? serie.dataCount : yAxis.runtimeMaxValue; - SetMinMax(visualMap, min, max); - break; + min = xAxis.IsCategory() ? 0 : xAxis.runtimeMinValue; + max = xAxis.IsCategory() ? serie.dataCount - 1 : xAxis.runtimeMaxValue; + SetMinMax(visualMap, min, max); + } + else + { + min = yAxis.IsCategory() ? 0 : yAxis.runtimeMinValue; + max = yAxis.IsCategory() ? serie.dataCount - 1 : yAxis.runtimeMaxValue; + SetMinMax(visualMap, min, max); } } @@ -54,55 +52,72 @@ namespace XCharts { startColor = ChartConst.clearColor32; toColor = ChartConst.clearColor32; - switch (visualMap.direction) + if (visualMap.dimension == 0) { - case VisualMap.Direction.Default: - case VisualMap.Direction.X: - startColor = visualMap.IsPiecewise() ? visualMap.GetColor(xValue) : visualMap.GetColor(xValue - 1); - toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(xValue); - break; - case VisualMap.Direction.Y: - startColor = visualMap.IsPiecewise() ? visualMap.GetColor(yValue) : visualMap.GetColor(yValue - 1); - toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(yValue); - break; + startColor = visualMap.IsPiecewise() ? visualMap.GetColor(xValue) : visualMap.GetColor(xValue - 1); + toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(xValue); + } + else + { + startColor = visualMap.IsPiecewise() ? visualMap.GetColor(yValue) : visualMap.GetColor(yValue - 1); + toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(yValue); } } - public static Color32 GetLineGradientColor(VisualMap visualMap, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor) + public static Color32 GetLineGradientColor(VisualMap visualMap, Vector3 pos, CoordinateChart chart, Axis axis, + Color32 defaultColor) { float value = 0; - switch (visualMap.direction) + var min = 0f; + var max = 0f; + if (visualMap.dimension == 0) { - case VisualMap.Direction.Default: - case VisualMap.Direction.X: - var min = axis.runtimeMinValue; - var max = axis.runtimeMaxValue; - var grid = chart.GetAxisGridOrDefault(axis); + min = axis.runtimeMinValue; + max = axis.runtimeMaxValue; + var grid = chart.GetAxisGridOrDefault(axis); + if (axis.IsCategory() && axis.boundaryGap) + { + float startX = grid.runtimeX + axis.runtimeScaleWidth / 2; + value = (int)(min + (pos.x - startX) / (grid.runtimeWidth - axis.runtimeScaleWidth) * (max - min)); + } + else + { value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min); - break; - case VisualMap.Direction.Y: - if (axis is YAxis) - { - var yAxis = chart.xAxes[axis.index]; - min = yAxis.runtimeMinValue; - max = yAxis.runtimeMaxValue; - } - else - { - var yAxis = chart.yAxes[axis.index]; - min = yAxis.runtimeMinValue; - max = yAxis.runtimeMaxValue; - } - grid = chart.GetAxisGridOrDefault(axis); + } + } + else + { + Axis yAxis; + if (axis is YAxis) + { + yAxis = chart.xAxes[axis.index]; + min = yAxis.runtimeMinValue; + max = yAxis.runtimeMaxValue; + } + else + { + yAxis = chart.yAxes[axis.index]; + min = yAxis.runtimeMinValue; + max = yAxis.runtimeMaxValue; + } + var grid = chart.GetAxisGridOrDefault(axis); + if (yAxis.IsCategory() && yAxis.boundaryGap) + { + float startY = grid.runtimeY + yAxis.runtimeScaleWidth / 2; + value = (int)(min + (pos.y - startY) / (grid.runtimeHeight - yAxis.runtimeScaleWidth) * (max - min)); + } + else + { value = min + (pos.y - grid.runtimeY) / grid.runtimeHeight * (max - min); - break; + } } var color = visualMap.GetColor(value); if (ChartHelper.IsClearColor(color)) return defaultColor; else return color; } - public static Color32 GetItemStyleGradientColor(ItemStyle itemStyle, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor) + public static Color32 GetItemStyleGradientColor(ItemStyle itemStyle, Vector3 pos, CoordinateChart chart, + Axis axis, Color32 defaultColor) { var min = axis.runtimeMinValue; var max = axis.runtimeMaxValue; @@ -114,7 +129,8 @@ namespace XCharts else return color; } - public static Color32 GetLineStyleGradientColor(LineStyle lineStyle, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor) + public static Color32 GetLineStyleGradientColor(LineStyle lineStyle, Vector3 pos, CoordinateChart chart, + Axis axis, Color32 defaultColor) { var min = axis.runtimeMinValue; var max = axis.runtimeMaxValue; diff --git a/Runtime/Internal/CoordinateChart.cs b/Runtime/Internal/CoordinateChart.cs index b1fcb43a..bb204130 100644 --- a/Runtime/Internal/CoordinateChart.cs +++ b/Runtime/Internal/CoordinateChart.cs @@ -878,7 +878,7 @@ namespace XCharts if (axis.IsCategory()) { axis.runtimeMinValue = 0; - axis.runtimeMaxValue = SeriesHelper.GetMaxSerieDataCount(m_Series); + axis.runtimeMaxValue = SeriesHelper.GetMaxSerieDataCount(m_Series) - 1; return; } float tempMinValue = 0; diff --git a/Runtime/Internal/CoordinateChart_DrawLine.cs b/Runtime/Internal/CoordinateChart_DrawLine.cs index 1186499e..5effc58f 100644 --- a/Runtime/Internal/CoordinateChart_DrawLine.cs +++ b/Runtime/Internal/CoordinateChart_DrawLine.cs @@ -108,6 +108,7 @@ namespace XCharts m_StackSerieData.Clear(); if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData); float scaleWid = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom); + xAxis.runtimeScaleWidth = scaleWid; float startX = grid.runtimeX + (xAxis.boundaryGap ? scaleWid / 2 : 0); int maxCount = serie.maxShow > 0 ? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow) diff --git a/Runtime/LineChart.cs b/Runtime/LineChart.cs index ad4c711b..f469d0fc 100644 --- a/Runtime/LineChart.cs +++ b/Runtime/LineChart.cs @@ -27,7 +27,6 @@ namespace XCharts visualMap.enable = false; visualMap.show = false; visualMap.autoMinMax = true; - visualMap.direction = VisualMap.Direction.Y; visualMap.inRange.Clear(); visualMap.inRange.Add(Color.blue); visualMap.inRange.Add(Color.red);