From 705652d50c7d2ed43eee1ca654f14e3a69e2f871 Mon Sep 17 00:00:00 2001 From: monitor1394 Date: Tue, 10 Mar 2020 09:12:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0`LineChart`=E7=9A=84=E6=99=AE?= =?UTF-8?q?=E9=80=9A=E6=8A=98=E7=BA=BF=E5=9B=BE=E5=8F=AF=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE`ingore`=E5=8F=82=E6=95=B0=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + Documentation/XCharts配置项手册.md | 3 + Editor/PropertyDrawers/SerieDrawer.cs | 11 +- Editor/PropertyDrawers/TooltipDrawer.cs | 5 +- Runtime/Component/Main/Serie.cs | 23 ++++ Runtime/Component/Main/Tooltip.cs | 5 + Runtime/Internal/CoordinateChart.cs | 8 +- Runtime/Internal/CoordinateChart_DrawLine.cs | 110 +++++++++++++++---- Runtime/Utility/ChartHelper.cs | 11 +- 9 files changed, 147 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae7307e..b09b5a01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 更新日志 +* (2020.03.10) 增加`LineChart`的普通折线图可通过设置`ingore`参数过滤数据的支持 * (2020.03.09) 增加`BarChart`可通过`ItemStyle`配置边框的支持 * (2020.03.08) 增加`RingChart`环形图 * (2020.03.05) 调整`Serie`的`arcShaped`参数重命名为`roundCap` diff --git a/Documentation/XCharts配置项手册.md b/Documentation/XCharts配置项手册.md index 7f2f00e6..fac559b9 100644 --- a/Documentation/XCharts配置项手册.md +++ b/Documentation/XCharts配置项手册.md @@ -205,6 +205,7 @@ * `paddingTopBottom`:文字和边框的上下边距。 * `backgroundImage`:提示框的背景图。 * `forceENotation`:是否强制使用科学计数法格式化显示数值。默认为false,当小数精度大于3时才采用科学计数法。 +* `ingoreDataDefaultContent`:被忽略数据的默认显示字符信息。 * `lineStyle`:指示器线条样式 [LineStyle](#LineStyle)。 * `textStyle`:显示内容文本样式 [TextStyle](#TextStyle)。 @@ -465,6 +466,8 @@ * `Sum`:取过滤点之和。 * `sampleAverage`:设定的采样平均值。当 `sampleType` 为 `Peak` 时,用于和过滤数据的平均值做对比是取最大值还是最小值。默认为`0`时会实时计算所有数据的平均值。 * `clip`:是否裁剪超出坐标系部分的图形。 +* `ingore`:是否开启忽略数据。当为 `true` 时,数据值为 `ingoreValue` 时不进行绘制。 +* `ingoreValue`:忽略数据的默认值。当 `ingore` 为 `true` 才有效。 * `areaStyle`:区域填充样式 [AreaStyle](#AreaStyle)。 * `symbol`:标记的图形 [SerieSymbol](#SerieSymbol)。 * `lineType`:折线图样式类型。支持以下十种类型: diff --git a/Editor/PropertyDrawers/SerieDrawer.cs b/Editor/PropertyDrawers/SerieDrawer.cs index 5c0345eb..ada2a532 100644 --- a/Editor/PropertyDrawers/SerieDrawer.cs +++ b/Editor/PropertyDrawers/SerieDrawer.cs @@ -71,6 +71,8 @@ namespace XCharts SerializedProperty m_GaugePointer = prop.FindPropertyRelative("m_GaugePointer"); SerializedProperty m_TitleStyle = prop.FindPropertyRelative("m_TitleStyle"); SerializedProperty m_Clip = prop.FindPropertyRelative("m_Clip"); + SerializedProperty m_Ingore = prop.FindPropertyRelative("m_Ingore"); + SerializedProperty m_IngoreValue = prop.FindPropertyRelative("m_IngoreValue"); SerializedProperty m_Datas = prop.FindPropertyRelative("m_Data"); int index = InitToggle(prop); @@ -122,6 +124,10 @@ namespace XCharts drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; EditorGUI.PropertyField(drawRect, m_Clip); drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_Ingore); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_IngoreValue); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; EditorGUI.PropertyField(drawRect, m_Symbol); drawRect.y += EditorGUI.GetPropertyHeight(m_Symbol); EditorGUI.PropertyField(drawRect, m_LineStyle); @@ -441,15 +447,12 @@ namespace XCharts } else { - SerializedProperty type = prop.FindPropertyRelative("m_Type"); var serieType = (SerieType)type.enumValueIndex; - - switch (serieType) { case SerieType.Line: - height += 14 * EditorGUIUtility.singleLineHeight + 13 * EditorGUIUtility.standardVerticalSpacing; + height += 16 * EditorGUIUtility.singleLineHeight + 15 * EditorGUIUtility.standardVerticalSpacing; height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_Symbol")); height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_LineStyle")); height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_LineArrow")); diff --git a/Editor/PropertyDrawers/TooltipDrawer.cs b/Editor/PropertyDrawers/TooltipDrawer.cs index 77edf907..9016040e 100644 --- a/Editor/PropertyDrawers/TooltipDrawer.cs +++ b/Editor/PropertyDrawers/TooltipDrawer.cs @@ -32,6 +32,7 @@ namespace XCharts SerializedProperty m_PaddingLeftRight = prop.FindPropertyRelative("m_PaddingLeftRight"); SerializedProperty m_PaddingTopBottom = prop.FindPropertyRelative("m_PaddingTopBottom"); SerializedProperty m_BackgroundImage = prop.FindPropertyRelative("m_BackgroundImage"); + SerializedProperty m_IngoreDataDefaultContent = prop.FindPropertyRelative("m_IngoreDataDefaultContent"); SerializedProperty m_LineStyle = prop.FindPropertyRelative("m_LineStyle"); SerializedProperty m_TextStyle = prop.FindPropertyRelative("m_TextStyle"); @@ -64,6 +65,8 @@ namespace XCharts drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; EditorGUI.PropertyField(drawRect, m_ForceENotation); drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_IngoreDataDefaultContent); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; EditorGUI.PropertyField(drawRect, m_LineStyle); drawRect.y += EditorGUI.GetPropertyHeight(m_LineStyle); EditorGUI.PropertyField(drawRect, m_TextStyle); @@ -75,7 +78,7 @@ namespace XCharts public override float GetPropertyHeight(SerializedProperty prop, GUIContent label) { if (m_TooltipModuleToggle) - return 13 * EditorGUIUtility.singleLineHeight + 12 * EditorGUIUtility.standardVerticalSpacing + + return 14 * EditorGUIUtility.singleLineHeight + 13 * EditorGUIUtility.standardVerticalSpacing + EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_LineStyle")) + EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_TextStyle")); else diff --git a/Runtime/Component/Main/Serie.cs b/Runtime/Component/Main/Serie.cs index cdf39a38..d8971a86 100644 --- a/Runtime/Component/Main/Serie.cs +++ b/Runtime/Component/Main/Serie.cs @@ -254,6 +254,8 @@ namespace XCharts [SerializeField] private bool m_ShowDataName; [SerializeField] private bool m_ShowDataIcon; [SerializeField] private bool m_Clip = true; + [SerializeField] private bool m_Ingore = true; + [SerializeField] private float m_IngoreValue = 0; [SerializeField] private List m_Data = new List(); @@ -609,6 +611,22 @@ namespace XCharts set { if (PropertyUtility.SetStruct(ref m_RoundCap, value)) SetVerticesDirty(); } } /// + /// 是否开启忽略数据。当为 true 时,数据值为 ingoreValue 时不进行绘制。 + /// + public bool ingore + { + get { return m_Ingore; } + set { if (PropertyUtility.SetStruct(ref m_Ingore, value)) SetVerticesDirty(); } + } + /// + /// 忽略数据的默认值。当ingore为true才有效。 + /// + public float ingoreValue + { + get { return m_IngoreValue; } + set { if (PropertyUtility.SetStruct(ref m_IngoreValue, value)) SetVerticesDirty(); } + } + /// /// 仪表盘轴线。 /// public GaugeAxis gaugeAxis @@ -1538,6 +1556,11 @@ namespace XCharts return false; } + public bool IsIngoreValue(float value) + { + return m_Ingore && Mathf.Approximately(value, m_IngoreValue); + } + /// /// 更新运行时中心点和半径 /// diff --git a/Runtime/Component/Main/Tooltip.cs b/Runtime/Component/Main/Tooltip.cs index 36f7d5cf..2a004125 100644 --- a/Runtime/Component/Main/Tooltip.cs +++ b/Runtime/Component/Main/Tooltip.cs @@ -61,6 +61,7 @@ namespace XCharts [SerializeField] private bool m_ForceENotation = false; [SerializeField] private float m_PaddingLeftRight = 5f; [SerializeField] private float m_PaddingTopBottom = 5f; + [SerializeField] private string m_IngoreDataDefaultContent = "-"; [SerializeField] private Sprite m_BackgroundImage; [SerializeField] private TextStyle m_TextStyle = new TextStyle(18, FontStyle.Normal); [SerializeField] private LineStyle m_LineStyle = new LineStyle(LineStyle.Type.Solid, 0.7f); @@ -166,6 +167,10 @@ namespace XCharts /// public float paddingTopBottom { get { return m_PaddingTopBottom; } set { m_PaddingTopBottom = value; } } /// + /// 被忽略数据的默认显示字符信息。 + /// + public string ingoreDataDefaultContent { get { return m_IngoreDataDefaultContent; } set { m_IngoreDataDefaultContent = value; } } + /// /// The image of icon. /// 图标的图片。 /// diff --git a/Runtime/Internal/CoordinateChart.cs b/Runtime/Internal/CoordinateChart.cs index b2440016..f2579b1c 100644 --- a/Runtime/Internal/CoordinateChart.cs +++ b/Runtime/Internal/CoordinateChart.cs @@ -421,6 +421,7 @@ namespace XCharts string key = serie.name; float xValue, yValue; serie.GetXYData(index, m_DataZoom, out xValue, out yValue); + var isIngore = ChartHelper.IsIngore(serie.dataPoints[index]); if (isCartesian) { var serieData = serie.GetSerieData(index, m_DataZoom); @@ -433,10 +434,12 @@ namespace XCharts } else { + var valueTxt = isIngore ? m_Tooltip.ingoreDataDefaultContent : + ChartCached.FloatToStr(yValue, 0, m_Tooltip.forceENotation); sb.Append("\n") .Append("● ") .Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "") - .Append(ChartCached.FloatToStr(yValue, 0, m_Tooltip.forceENotation)); + .Append(valueTxt); } } } @@ -1438,7 +1441,8 @@ namespace XCharts for (int j = 0; j < serie.data.Count; j++) { var serieData = serie.data[j]; - if (serie.label.show || serieData.iconStyle.show) + var isIngore = ChartHelper.IsIngore(serie.dataPoints[j]); + if ((serie.label.show || serieData.iconStyle.show) && !isIngore) { var pos = serie.dataPoints[j]; var value = serieData.data[1]; diff --git a/Runtime/Internal/CoordinateChart_DrawLine.cs b/Runtime/Internal/CoordinateChart_DrawLine.cs index 1e212bef..4e81cfba 100644 --- a/Runtime/Internal/CoordinateChart_DrawLine.cs +++ b/Runtime/Internal/CoordinateChart_DrawLine.cs @@ -33,6 +33,7 @@ namespace XCharts if (serie.lineArrow.position == LineArrow.Position.End && i == count - 1) continue; } Vector3 p = serie.dataPoints[i]; + if (ChartHelper.IsIngore(p)) continue; bool highlight = (m_Tooltip.show && m_Tooltip.IsSelected(i)) || serie.data[i].highlighted || serie.highlighted; float symbolSize = highlight ? serie.symbol.selectedSize : serie.symbol.size; @@ -123,11 +124,18 @@ namespace XCharts { for (int j = 0; j < rate; j++) seriesHig.Add(0); } - float yValue = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage, - i, dataChangeDuration, ref dataChanging); - seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np, - dataChangeDuration); - serie.dataPoints.Add(np); + if (serie.IsIngoreValue(showData[i].GetData(1))) + { + serie.dataPoints.Add(Vector3.zero); + } + else + { + float yValue = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage, + i, dataChangeDuration, ref dataChanging); + seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np, + dataChangeDuration); + serie.dataPoints.Add(np); + } } if (dataChanging) { @@ -137,10 +145,17 @@ namespace XCharts { i = maxCount - 1; seriesHig.Add(0); - float yValue = showData[i].GetCurrData(1, dataChangeDuration); - seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np, - dataChangeDuration); - serie.dataPoints.Add(np); + if (serie.IsIngoreValue(showData[i].GetData(1))) + { + serie.dataPoints.Add(Vector3.zero); + } + else + { + float yValue = showData[i].GetCurrData(1, dataChangeDuration); + seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np, + dataChangeDuration); + serie.dataPoints.Add(np); + } } if (serie.dataPoints.Count <= 0) { @@ -156,8 +171,15 @@ namespace XCharts if (serie.minShow > 0 && serie.minShow < showData.Count) { i = serie.minShow - 1; - float yValue = showData[i].GetCurrData(1, dataChangeDuration); - GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref firstLastPos, dataChangeDuration); + if (serie.IsIngoreValue(showData[i].GetData(1))) + { + serie.dataPoints.Add(Vector3.zero); + } + else + { + float yValue = showData[i].GetCurrData(1, dataChangeDuration); + GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref firstLastPos, dataChangeDuration); + } } else { @@ -166,8 +188,15 @@ namespace XCharts if (serie.maxShow > 0 && serie.maxShow < showData.Count) { i = serie.maxShow; - float yValue = showData[i].GetCurrData(1, dataChangeDuration); - GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref lastNextPos, dataChangeDuration); + if (serie.IsIngoreValue(showData[i].GetData(1))) + { + serie.dataPoints.Add(Vector3.zero); + } + else + { + float yValue = showData[i].GetCurrData(1, dataChangeDuration); + GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref lastNextPos, dataChangeDuration); + } } else { @@ -177,7 +206,8 @@ namespace XCharts { np = serie.dataPoints[i]; serie.ClearSmoothList(i); - if (!serie.animation.NeedAnimation(i)) break; + //if(np == Vector3.zero) continue; + //if (!serie.animation.NeedAnimation(i)) break; bool isFinish = true; if (serie.areaStyle.tooltipHighlight && m_Tooltip.show && i <= m_Tooltip.runtimeDataIndex[0]) { @@ -192,21 +222,24 @@ namespace XCharts switch (serie.lineType) { case LineType.Normal: - nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : np; + nnp = GetNNPos(serie.dataPoints, i, np); isFinish = DrawNormalLine(vh, serie, xAxis, lp, np, nnp, i, lineColor, areaColor, areaToColor, zeroPos); break; case LineType.Smooth: case LineType.SmoothDash: - llp = i > 1 ? serie.dataPoints[i - 2] : firstLastPos; - nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : lastNextPos; + //llp = i > 1 ? serie.dataPoints[i - 2] : firstLastPos; + //nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : lastNextPos; + llp = GetLLPos(serie.dataPoints, i, firstLastPos); + nnp = GetNNPos(serie.dataPoints, i, lastNextPos); isFinish = DrawSmoothLine(vh, serie, xAxis, lp, np, llp, nnp, i, lineColor, areaColor, areaToColor, isStack, zeroPos); break; case LineType.StepStart: case LineType.StepMiddle: case LineType.StepEnd: - nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : np; + //nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : np; + nnp = GetNNPos(serie.dataPoints, i, np); isFinish = DrawStepLine(vh, serie, xAxis, lp, np, nnp, i, lineColor, areaColor, areaToColor, zeroPos); break; @@ -218,7 +251,7 @@ namespace XCharts break; } if (isFinish) serie.animation.SetDataFinish(i); - lp = np; + if (np != Vector3.zero) lp = np; } if (!serie.animation.IsFinish()) { @@ -229,6 +262,37 @@ namespace XCharts } } + private Vector3 GetNNPos(List dataPoints, int index, Vector3 np) + { + int size = dataPoints.Count; + if (index >= size) return np; + for (int i = index + 1; i < size; i++) + { + if (dataPoints[i] != Vector3.zero) return dataPoints[i]; + } + return np; + } + + private Vector3 GetLastPos(List dataPoints, int index, Vector3 pos) + { + if (index <= 0) return pos; + for (int i = index - 1; i > 0; i--) + { + if (dataPoints[i] != Vector3.zero) return dataPoints[i]; + } + return pos; + } + + private Vector3 GetLLPos(List dataPoints, int index, Vector3 lp) + { + if (index <= 1) return lp; + for (int i = index - 2; i > 0; i--) + { + if (dataPoints[i] != Vector3.zero) return dataPoints[i]; + } + return lp; + } + private float DataAverage(ref List showData, SampleType sampleType, int minCount, int maxCount, int rate) { var totalAverage = 0f; @@ -303,8 +367,13 @@ namespace XCharts } private float GetDataPoint(Axis xAxis, Axis yAxis, List showData, float yValue, float startX, int i, - float scaleWid, float serieHig, ref Vector3 np, float duration) + float scaleWid, float serieHig, ref Vector3 np, float duration, bool isIngoreValue = false) { + if (isIngoreValue) + { + np = Vector3.zero; + return 0; + } float xDataHig, yDataHig; float xMinValue = xAxis.GetCurrMinValue(duration); float xMaxValue = xAxis.GetCurrMaxValue(duration); @@ -355,7 +424,6 @@ namespace XCharts else yDataHig = (yValue - yMinValue) / (yMaxValue - yMinValue) * coordinateHeight; } np = new Vector3(pX, pY + yDataHig); - } return yDataHig; } diff --git a/Runtime/Utility/ChartHelper.cs b/Runtime/Utility/ChartHelper.cs index 05b4bf17..cc2fccb3 100644 --- a/Runtime/Utility/ChartHelper.cs +++ b/Runtime/Utility/ChartHelper.cs @@ -21,8 +21,15 @@ namespace XCharts public static class ChartHelper { private static StringBuilder s_Builder = new StringBuilder(); + private static Vector3 s_DefaultIngoreDataVector3 = Vector3.zero; public static StringBuilder sb { get { return s_Builder; } } + public static Vector3 ingoreVector3 { get { return s_DefaultIngoreDataVector3; } } + + public static bool IsIngore(Vector3 pos) + { + return pos == s_DefaultIngoreDataVector3; + } public static string Cancat(string str1, string str2) { s_Builder.Length = 0; @@ -93,12 +100,12 @@ namespace XCharts #if UNITY_2019_1_OR_NEWER #else if (parent == null) return; - #if UNITY_EDITOR && UNITY_2018_3_OR_NEWER +#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER if (PrefabUtility.IsPartOfAnyPrefab(parent.gameObject)) { return; } - #endif +#endif while (parent.childCount > 0) { var go = parent.GetChild(0);