mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-21 16:00:24 +00:00
3.0 - unitypackage
This commit is contained in:
145
Runtime/Helper/CheckHelper.cs
Normal file
145
Runtime/Helper/CheckHelper.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class CheckHelper
|
||||
{
|
||||
private static bool IsColorAlphaZero(Color color)
|
||||
{
|
||||
return !ChartHelper.IsClearColor(color) && color.a == 0;
|
||||
}
|
||||
|
||||
public static string CheckChart(BaseGraph chart)
|
||||
{
|
||||
if (chart is BaseChart) return CheckChart((BaseChart)chart);
|
||||
else return string.Empty;
|
||||
}
|
||||
|
||||
public static string CheckChart(BaseChart chart)
|
||||
{
|
||||
var sb = ChartHelper.sb;
|
||||
sb.Length = 0;
|
||||
CheckName(chart, sb);
|
||||
CheckSize(chart, sb);
|
||||
CheckTheme(chart, sb);
|
||||
CheckTitle(chart, sb);
|
||||
CheckLegend(chart, sb);
|
||||
CheckGrid(chart, sb);
|
||||
CheckSerie(chart, sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static void CheckName(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
if (string.IsNullOrEmpty(chart.chartName)) return;
|
||||
var list = XChartsMgr.GetCharts(chart.chartName);
|
||||
if (list.Count > 1)
|
||||
{
|
||||
sb.AppendFormat("warning:chart name is repeated: {0}\n", chart.chartName);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckSize(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
if (chart.chartWidth == 0 || chart.chartHeight == 0)
|
||||
{
|
||||
sb.Append("warning:chart width or height is 0\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckTheme(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
var theme = chart.theme;
|
||||
theme.CheckWarning(sb);
|
||||
}
|
||||
|
||||
private static void CheckTitle(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
// foreach (var title in chart.titles)
|
||||
// {
|
||||
// if (!title.show) return;
|
||||
// if (string.IsNullOrEmpty(title.text)) sb.AppendFormat("warning:title{0}->text is null\n", title.index);
|
||||
// if (IsColorAlphaZero(title.textStyle.color))
|
||||
// sb.AppendFormat("warning:title{0}->textStyle->color alpha is 0\n", title.index);
|
||||
// if (IsColorAlphaZero(title.subTextStyle.color))
|
||||
// sb.AppendFormat("warning:title{0}->subTextStyle->color alpha is 0\n", title.index);
|
||||
// }
|
||||
}
|
||||
|
||||
private static void CheckLegend(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
}
|
||||
|
||||
private static void CheckGrid(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
}
|
||||
|
||||
private static void CheckSerie(BaseChart chart, StringBuilder sb)
|
||||
{
|
||||
var allDataIsEmpty = true;
|
||||
var allDataIsZero = true;
|
||||
var allSerieIsHide = true;
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie.show) allSerieIsHide = false;
|
||||
if (serie.dataCount > 0)
|
||||
{
|
||||
allDataIsEmpty = false;
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.GetSerieData(i);
|
||||
for (int j = 1; j < serieData.data.Count; j++)
|
||||
{
|
||||
if (serieData.GetData(j) != 0)
|
||||
{
|
||||
allDataIsZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var dataCount = serie.GetSerieData(0).data.Count;
|
||||
if (serie.showDataDimension > 1 && serie.showDataDimension != dataCount)
|
||||
{
|
||||
sb.AppendFormat("warning:serie {0} serieData.data.count[{1}] not match showDataDimension[{2}]\n", serie.index, dataCount, serie.showDataDimension);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat("warning:serie {0} no data\n", serie.index);
|
||||
}
|
||||
if (IsColorAlphaZero(serie.itemStyle.color))
|
||||
sb.AppendFormat("warning:serie {0} itemStyle->color alpha is 0\n", serie.index);
|
||||
if (serie.itemStyle.opacity == 0)
|
||||
sb.AppendFormat("warning:serie {0} itemStyle->opacity is 0\n", serie.index);
|
||||
if (serie.itemStyle.borderWidth != 0 && IsColorAlphaZero(serie.itemStyle.borderColor))
|
||||
sb.AppendFormat("warning:serie {0} itemStyle->borderColor alpha is 0\n", serie.index);
|
||||
if (serie is Line)
|
||||
{
|
||||
if (serie.lineStyle.opacity == 0)
|
||||
sb.AppendFormat("warning:serie {0} lineStyle->opacity is 0\n", serie.index);
|
||||
if (IsColorAlphaZero(serie.lineStyle.color))
|
||||
sb.AppendFormat("warning:serie {0} lineStyle->color alpha is 0\n", serie.index);
|
||||
}
|
||||
else if (serie is Bar)
|
||||
{
|
||||
if (serie.barWidth == 0)
|
||||
sb.AppendFormat("warning:serie {0} barWidth is 0\n", serie.index);
|
||||
}
|
||||
else if (serie is Pie)
|
||||
{
|
||||
if (serie.radius.Length >= 2 && serie.radius[1] == 0)
|
||||
sb.AppendFormat("warning:serie {0} radius[1] is 0\n", serie.index);
|
||||
}
|
||||
else if (serie is Scatter || serie is EffectScatter)
|
||||
{
|
||||
if (!serie.symbol.show)
|
||||
sb.AppendFormat("warning:serie {0} symbol type is None\n", serie.index);
|
||||
}
|
||||
}
|
||||
if (allDataIsEmpty) sb.Append("warning:all serie data is empty\n");
|
||||
if (!allDataIsEmpty && allDataIsZero) sb.Append("warning:all serie data is 0\n");
|
||||
if (allSerieIsHide) sb.Append("warning:all serie is hide\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Helper/CheckHelper.cs.meta
Normal file
11
Runtime/Helper/CheckHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09a50ff0a7fdb4174b4dc2d28fc08b6a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
258
Runtime/Helper/FormatterHelper.cs
Normal file
258
Runtime/Helper/FormatterHelper.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class FormatterHelper
|
||||
{
|
||||
public const string PH_NN = "\n";
|
||||
private static Regex s_Regex = new Regex(@"{([a-e|.]\d*)(:\d+(-\d+)?)?(:[c-g|x|p|r]\d*|:0\.#*)?}", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexSub = new Regex(@"(0\.#*)|(\d+-\d+)|(\w+)|(\.)", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexN = new Regex(@"^\d+", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexN_N = new Regex(@"\d+-\d+", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexFn = new Regex(@"[c-g|x|p|r]\d*|0\.#*", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexNewLine = new Regex(@"[\\|/]+n|</br>|<br>|<br/>", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexForAxisLabel = new Regex(@"{value(:[c-g|x|p|r]\d*)?}", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexSubForAxisLabel = new Regex(@"(value)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexForSerieLabel = new Regex(@"{[a-e|\.](:[c-g|x|p|r]\d*)?}", RegexOptions.IgnoreCase);
|
||||
private static Regex s_RegexSubForSerieLabel = new Regex(@"(\.)|([a-e])|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// 替换字符串中的通配符,支持的通配符有{.}、{a}、{b}、{c}、{d}、{e}。
|
||||
/// </summary>
|
||||
/// <param name="content">要替换的字符串</param>
|
||||
/// <param name="dataIndex">选中的数据项serieData索引</param>
|
||||
/// <param name="numericFormatter">默认的数字格式化</param>
|
||||
/// <param name="serie">选中的serie</param>
|
||||
/// <param name="series">所有serie</param>
|
||||
/// <param name="theme">用来获取指定index的颜色</param>
|
||||
/// <param name="category">选中的类目,一般用在折线图和柱状图</param>
|
||||
/// <param name="dataZoom">dataZoom</param>
|
||||
/// <returns></returns>
|
||||
public static bool ReplaceContent(ref string content, int dataIndex, string numericFormatter, Serie serie,
|
||||
BaseChart chart, DataZoom dataZoom = null)
|
||||
{
|
||||
var foundDot = false;
|
||||
var mc = s_Regex.Matches(content);
|
||||
foreach (var m in mc)
|
||||
{
|
||||
var old = m.ToString();
|
||||
var args = s_RegexSub.Matches(m.ToString());
|
||||
var argsCount = args.Count;
|
||||
if (argsCount <= 0) continue;
|
||||
int targetIndex = 0;
|
||||
char p = GetSerieIndex(args[0].ToString(), ref targetIndex);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
serie = chart.GetSerie(targetIndex);
|
||||
if (serie == null) continue;
|
||||
}
|
||||
else if (serie != null)
|
||||
{
|
||||
targetIndex = serie.index;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie = chart.GetSerie(0);
|
||||
targetIndex = 0;
|
||||
}
|
||||
if (serie == null) continue;
|
||||
if (p == '.')
|
||||
{
|
||||
var bIndex = targetIndex;
|
||||
if (argsCount >= 2)
|
||||
{
|
||||
var args1Str = args[1].ToString();
|
||||
if (s_RegexN.IsMatch(args1Str)) bIndex = int.Parse(args1Str);
|
||||
}
|
||||
content = content.Replace(old, ChartCached.ColorToDotStr(chart.theme.GetColor(bIndex)));
|
||||
foundDot = true;
|
||||
}
|
||||
else if (p == 'a' || p == 'A')
|
||||
{
|
||||
if (argsCount == 1)
|
||||
{
|
||||
content = content.Replace(old, serie.serieName);
|
||||
}
|
||||
}
|
||||
else if (p == 'b' || p == 'B' || p == 'e' || p == 'E')
|
||||
{
|
||||
var bIndex = dataIndex;
|
||||
if (argsCount >= 2)
|
||||
{
|
||||
var args1Str = args[1].ToString();
|
||||
if (s_RegexN.IsMatch(args1Str)) bIndex = int.Parse(args1Str);
|
||||
}
|
||||
var needCategory = (p != 'e' && p != 'E') && (serie is Line || serie is Bar);
|
||||
if (needCategory)
|
||||
{
|
||||
var category = chart.GetTooltipCategory(dataIndex, serie, dataZoom);
|
||||
content = content.Replace(old, category);
|
||||
}
|
||||
else
|
||||
{
|
||||
var serieData = serie.GetSerieData(bIndex, dataZoom);
|
||||
content = content.Replace(old, serieData.name);
|
||||
}
|
||||
}
|
||||
else if (p == 'c' || p == 'C' || p == 'd' || p == 'D')
|
||||
{
|
||||
var isPercent = p == 'd' || p == 'D';
|
||||
var bIndex = dataIndex;
|
||||
var dimensionIndex = -1;
|
||||
if (argsCount >= 2)
|
||||
{
|
||||
var args1Str = args[1].ToString();
|
||||
if (s_RegexFn.IsMatch(args1Str))
|
||||
{
|
||||
numericFormatter = args1Str;
|
||||
}
|
||||
else if (s_RegexN_N.IsMatch(args1Str))
|
||||
{
|
||||
var temp = args1Str.Split('-');
|
||||
bIndex = int.Parse(temp[0]);
|
||||
dimensionIndex = int.Parse(temp[1]);
|
||||
}
|
||||
else if (s_RegexN.IsMatch(args1Str))
|
||||
{
|
||||
dimensionIndex = int.Parse(args1Str);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("unmatch:" + args1Str);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (argsCount >= 3)
|
||||
{
|
||||
numericFormatter = args[2].ToString();
|
||||
}
|
||||
if (dimensionIndex == -1) dimensionIndex = 1;
|
||||
if (numericFormatter == string.Empty)
|
||||
{
|
||||
numericFormatter = SerieHelper.GetNumericFormatter(serie, serie.GetSerieData(bIndex));
|
||||
}
|
||||
var value = serie.GetData(bIndex, dimensionIndex, dataZoom);
|
||||
if (isPercent)
|
||||
{
|
||||
var total = serie.GetDataTotal(dimensionIndex);
|
||||
var percent = total == 0 ? 0 : value / serie.yTotal * 100;
|
||||
content = content.Replace(old, ChartCached.FloatToStr(percent, numericFormatter));
|
||||
}
|
||||
else
|
||||
{
|
||||
content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
}
|
||||
}
|
||||
content = s_RegexNewLine.Replace(content, PH_NN);
|
||||
return foundDot;
|
||||
}
|
||||
|
||||
private static char GetSerieIndex(string strType, ref int index)
|
||||
{
|
||||
index = -1;
|
||||
if (strType.Length > 1)
|
||||
{
|
||||
if (!int.TryParse(strType.Substring(1), out index))
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
return strType.ElementAt(0);
|
||||
}
|
||||
|
||||
public static string TrimAndReplaceLine(StringBuilder sb)
|
||||
{
|
||||
return TrimAndReplaceLine(sb.ToString());
|
||||
}
|
||||
|
||||
public static string TrimAndReplaceLine(string content)
|
||||
{
|
||||
return s_RegexNewLine.Replace(content.Trim(), PH_NN);
|
||||
}
|
||||
|
||||
public static void ReplaceAxisLabelContent(ref string content, string numericFormatter, double value)
|
||||
{
|
||||
var mc = s_RegexForAxisLabel.Matches(content);
|
||||
foreach (var m in mc)
|
||||
{
|
||||
var old = m.ToString();
|
||||
var args = s_RegexSubForAxisLabel.Matches(m.ToString());
|
||||
var argsCount = args.Count;
|
||||
if (argsCount <= 0) continue;
|
||||
if (argsCount >= 2)
|
||||
{
|
||||
numericFormatter = args[1].ToString();
|
||||
}
|
||||
content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
content = TrimAndReplaceLine(content);
|
||||
}
|
||||
|
||||
public static void ReplaceAxisLabelContent(ref string content, string value)
|
||||
{
|
||||
var mc = s_RegexForAxisLabel.Matches(content);
|
||||
foreach (var m in mc)
|
||||
{
|
||||
var old = m.ToString();
|
||||
var args = s_RegexSubForAxisLabel.Matches(m.ToString());
|
||||
var argsCount = args.Count;
|
||||
if (argsCount <= 0) continue;
|
||||
content = content.Replace(old, value);
|
||||
}
|
||||
content = TrimAndReplaceLine(content);
|
||||
}
|
||||
|
||||
public static void ReplaceSerieLabelContent(ref string content, string numericFormatter, double value, double total,
|
||||
string serieName, string category, string dataName, Color color)
|
||||
{
|
||||
var mc = s_RegexForSerieLabel.Matches(content);
|
||||
foreach (var m in mc)
|
||||
{
|
||||
var old = m.ToString();
|
||||
var args = s_RegexSubForSerieLabel.Matches(old);
|
||||
var argsCount = args.Count;
|
||||
if (argsCount <= 0) continue;
|
||||
var p = args[0].ToString().ElementAt(0);
|
||||
if (argsCount >= 2)
|
||||
{
|
||||
numericFormatter = args[1].ToString();
|
||||
}
|
||||
if (p == '.')
|
||||
{
|
||||
content = content.Replace(old, ChartCached.ColorToDotStr(color));
|
||||
}
|
||||
else if (p == 'a' || p == 'A')
|
||||
{
|
||||
content = content.Replace(old, serieName);
|
||||
}
|
||||
else if (p == 'b' || p == 'B')
|
||||
{
|
||||
content = content.Replace(old, category);
|
||||
}
|
||||
else if (p == 'e' || p == 'E')
|
||||
{
|
||||
content = content.Replace(old, dataName);
|
||||
}
|
||||
else if (p == 'c' || p == 'C' || p == 'd' || p == 'D')
|
||||
{
|
||||
var isPercent = p == 'd' || p == 'D';
|
||||
if (isPercent)
|
||||
{
|
||||
if (total != 0)
|
||||
content = content.Replace(old, ChartCached.FloatToStr(value / total * 100, numericFormatter));
|
||||
}
|
||||
else
|
||||
{
|
||||
content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
}
|
||||
}
|
||||
content = TrimAndReplaceLine(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Helper/FormatterHelper.cs.meta
Normal file
11
Runtime/Helper/FormatterHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fddcb81df44148ed86496564b120261
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
776
Runtime/Helper/SerieHelper.cs
Normal file
776
Runtime/Helper/SerieHelper.cs
Normal file
@@ -0,0 +1,776 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static partial class SerieHelper
|
||||
{
|
||||
public static double GetMinData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
|
||||
{
|
||||
double min = double.MaxValue;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (value < min && !serie.IsIgnoreValue(value)) min = value;
|
||||
}
|
||||
}
|
||||
return min == double.MaxValue ? 0 : min;
|
||||
}
|
||||
public static SerieData GetMinSerieData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
|
||||
{
|
||||
double min = double.MaxValue;
|
||||
SerieData minData = null;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (value < min && !serie.IsIgnoreValue(value))
|
||||
{
|
||||
min = value;
|
||||
minData = serieData;
|
||||
}
|
||||
}
|
||||
}
|
||||
return minData;
|
||||
}
|
||||
public static double GetMaxData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
|
||||
{
|
||||
double max = double.MinValue;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (value > max && !serie.IsIgnoreValue(value)) max = value;
|
||||
}
|
||||
}
|
||||
return max == double.MinValue ? 0 : max;
|
||||
}
|
||||
public static SerieData GetMaxSerieData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
|
||||
{
|
||||
double max = double.MinValue;
|
||||
SerieData maxData = null;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (value > max && !serie.IsIgnoreValue(value))
|
||||
{
|
||||
max = value;
|
||||
maxData = serieData;
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxData;
|
||||
}
|
||||
|
||||
public static double GetAverageData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
|
||||
{
|
||||
double total = 0;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (!serie.IsIgnoreValue(value))
|
||||
total += value;
|
||||
}
|
||||
}
|
||||
return total != 0 ? total / dataList.Count : 0;
|
||||
}
|
||||
|
||||
private static List<double> s_TempList = new List<double>();
|
||||
public static double GetMedianData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
|
||||
{
|
||||
s_TempList.Clear();
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (!serie.IsIgnoreValue(value))
|
||||
s_TempList.Add(value);
|
||||
}
|
||||
}
|
||||
s_TempList.Sort();
|
||||
var n = s_TempList.Count;
|
||||
if (n % 2 == 0) return (s_TempList[n / 2] + s_TempList[n / 2 - 1]) / 2;
|
||||
else return s_TempList[n / 2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum and minimum values of the specified dimension of a serie.
|
||||
/// 获得系列指定维数的最大最小值。
|
||||
/// </summary>
|
||||
/// <param name="serie">指定系列</param>
|
||||
/// <param name="dimension">指定维数</param>
|
||||
/// <param name="min">最小值</param>
|
||||
/// <param name="max">最大值</param>
|
||||
/// <param name="dataZoom">缩放组件,默认null</param>
|
||||
public static void GetMinMaxData(Serie serie, int dimension, out double min, out double max,
|
||||
DataZoom dataZoom = null)
|
||||
{
|
||||
max = double.MinValue;
|
||||
min = double.MaxValue;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show && serieData.data.Count > dimension)
|
||||
{
|
||||
var value = serieData.data[dimension];
|
||||
if (!serie.IsIgnoreValue(value))
|
||||
{
|
||||
if (value > max) max = value;
|
||||
if (value < min) min = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum and minimum values of all data in the serie.
|
||||
/// 获得系列所有数据的最大最小值。
|
||||
/// </summary>
|
||||
/// <param name="serie"></param>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
public static void GetMinMaxData(Serie serie, out double min, out double max, DataZoom dataZoom = null, int dimension = 0)
|
||||
{
|
||||
max = double.MinValue;
|
||||
min = double.MaxValue;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var serieData = dataList[i];
|
||||
if (serieData.show)
|
||||
{
|
||||
var count = 0;
|
||||
if (dimension > 0) count = dimension;
|
||||
else count = serie.showDataDimension > serieData.data.Count
|
||||
? serieData.data.Count
|
||||
: serie.showDataDimension;
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
var value = serieData.data[j];
|
||||
if (!serie.IsIgnoreValue(value))
|
||||
{
|
||||
if (value > max) max = value;
|
||||
if (value < min) min = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the data for the specified dimension of serie are all 0.
|
||||
/// 系列指定维数的数据是否全部为0。
|
||||
/// </summary>
|
||||
/// <param name="serie">系列</param>
|
||||
/// <param name="dimension">指定维数</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAllZeroValue(Serie serie, int dimension = 1)
|
||||
{
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.GetData(dimension) != 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新运行时中心点和半径
|
||||
/// </summary>
|
||||
/// <param name="chartWidth"></param>
|
||||
/// <param name="chartHeight"></param>
|
||||
public static void UpdateCenter(Serie serie, Vector3 chartPosition, float chartWidth, float chartHeight)
|
||||
{
|
||||
if (serie.center.Length < 2) return;
|
||||
var centerX = serie.center[0] <= 1 ? chartWidth * serie.center[0] : serie.center[0];
|
||||
var centerY = serie.center[1] <= 1 ? chartHeight * serie.center[1] : serie.center[1];
|
||||
serie.context.center = chartPosition + new Vector3(centerX, centerY);
|
||||
var minWidth = Mathf.Min(chartWidth, chartHeight);
|
||||
serie.context.insideRadius = serie.radius[0] <= 1 ? minWidth * serie.radius[0] : serie.radius[0];
|
||||
serie.context.outsideRadius = serie.radius[1] <= 1 ? minWidth * serie.radius[1] : serie.radius[1];
|
||||
}
|
||||
|
||||
public static void UpdateRect(Serie serie, Vector3 chartPosition, float chartWidth, float chartHeight)
|
||||
{
|
||||
if (serie.left != 0 || serie.right != 0 || serie.top != 0 || serie.bottom != 0)
|
||||
{
|
||||
var runtimeLeft = serie.left <= 1 ? serie.left * chartWidth : serie.left;
|
||||
var runtimeBottom = serie.bottom <= 1 ? serie.bottom * chartHeight : serie.bottom;
|
||||
var runtimeTop = serie.top <= 1 ? serie.top * chartHeight : serie.top;
|
||||
var runtimeRight = serie.right <= 1 ? serie.right * chartWidth : serie.right;
|
||||
|
||||
serie.context.x = chartPosition.x + runtimeLeft;
|
||||
serie.context.y = chartPosition.y + runtimeBottom;
|
||||
serie.context.width = chartWidth - runtimeLeft - runtimeRight;
|
||||
serie.context.height = chartHeight - runtimeTop - runtimeBottom;
|
||||
serie.context.center = new Vector3(serie.context.x + serie.context.width / 2,
|
||||
serie.context.y + serie.context.height / 2);
|
||||
serie.context.rect = new Rect(serie.context.x, serie.context.y, serie.context.width, serie.context.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.x = chartPosition.x;
|
||||
serie.context.y = chartPosition.y;
|
||||
serie.context.width = chartWidth;
|
||||
serie.context.height = chartHeight;
|
||||
serie.context.center = chartPosition + new Vector3(chartWidth / 2, chartHeight / 2);
|
||||
serie.context.rect = new Rect(serie.context.x, serie.context.y, serie.context.width, serie.context.height);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color32 GetItemBackgroundColor(Serie serie, SerieData serieData, ThemeStyle theme, int index,
|
||||
bool highlight, bool useDefault = true)
|
||||
{
|
||||
var color = ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.backgroundColor))
|
||||
{
|
||||
color = itemStyleEmphasis.backgroundColor;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.backgroundColor))
|
||||
{
|
||||
color = itemStyle.backgroundColor;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
else if (useDefault)
|
||||
{
|
||||
color = theme.GetColor(index);
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
color.a = 50;
|
||||
return color;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
public static Color32 GetItemColor(Serie serie, SerieData serieData, ThemeStyle theme, int index, bool highlight)
|
||||
{
|
||||
if (serie == null) return ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
|
||||
{
|
||||
var color = itemStyleEmphasis.color;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.color))
|
||||
{
|
||||
return itemStyle.GetColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = theme.GetColor(index);
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
public static Color32 GetItemColor0(Serie serie, SerieData serieData, ThemeStyle theme, bool highlight, Color32 defaultColor)
|
||||
{
|
||||
if (serie == null) return ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
|
||||
{
|
||||
var color = itemStyleEmphasis.color0;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.color0))
|
||||
{
|
||||
return itemStyle.GetColor0();
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = defaultColor;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color32 GetItemToColor(Serie serie, SerieData serieData, ThemeStyle theme, int index, bool highlight)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.toColor))
|
||||
{
|
||||
return itemStyleEmphasis.GetColor();
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle == null) itemStyle = serieData.itemStyle;
|
||||
if (!ChartHelper.IsClearColor(itemStyle.toColor))
|
||||
{
|
||||
var color = itemStyle.toColor;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
if (!ChartHelper.IsClearColor(itemStyle.color))
|
||||
{
|
||||
var color = itemStyle.color;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = theme.GetColor(index);
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsDownPoint(Serie serie, int index)
|
||||
{
|
||||
var dataPoints = serie.context.dataPoints;
|
||||
if (dataPoints.Count < 2) return false;
|
||||
else if (index > 0 && index < dataPoints.Count - 1)
|
||||
{
|
||||
var lp = dataPoints[index - 1];
|
||||
var np = dataPoints[index + 1];
|
||||
var cp = dataPoints[index];
|
||||
var dot = Vector3.Cross(np - lp, cp - np);
|
||||
return dot.z < 0;
|
||||
}
|
||||
else if (index == 0)
|
||||
{
|
||||
return dataPoints[0].y < dataPoints[1].y;
|
||||
}
|
||||
else if (index == dataPoints.Count - 1)
|
||||
{
|
||||
return dataPoints[index].y < dataPoints[index - 1].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStyle GetItemStyle(Serie serie, SerieData serieData, bool highlight = false)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
var style = GetItemStyleEmphasis(serie, serieData);
|
||||
if (style == null) return GetItemStyle(serie, serieData, false);
|
||||
else return style;
|
||||
}
|
||||
else if (serie.IsPerformanceMode()) return serie.itemStyle;
|
||||
else if (serieData != null && serieData.itemStyle != null) return serieData.itemStyle;
|
||||
else return serie.itemStyle;
|
||||
}
|
||||
|
||||
public static ItemStyle GetItemStyleEmphasis(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData != null && serieData.emphasis != null && serieData.emphasis.show)
|
||||
return serieData.emphasis.itemStyle;
|
||||
else if (serie.emphasis != null && serie.emphasis.show) return serie.emphasis.itemStyle;
|
||||
else return null;
|
||||
}
|
||||
|
||||
public static LabelStyle GetSerieLabel(Serie serie, SerieData serieData, bool highlight = false)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.emphasis != null && serieData.emphasis.show)
|
||||
return serieData.emphasis.label;
|
||||
else if (serie.emphasis != null && serie.emphasis.show) return serie.emphasis.label;
|
||||
else return serie.label;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.label != null) return serieData.label;
|
||||
else return serie.label;
|
||||
}
|
||||
}
|
||||
|
||||
public static LabelStyle GetSerieEmphasisLabel(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.emphasis != null && serieData.emphasis.show)
|
||||
return serieData.emphasis.label;
|
||||
else if (serie.emphasis != null && serie.emphasis.show) return serie.emphasis.label;
|
||||
else return null;
|
||||
}
|
||||
|
||||
public static LabelLine GetSerieLabelLine(Serie serie, SerieData serieData, bool highlight = false)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.emphasis != null && serieData.emphasis.show)
|
||||
return serieData.emphasis.labelLine;
|
||||
else if (serie.emphasis != null && serie.emphasis.show) return serie.emphasis.labelLine;
|
||||
else return serie.labelLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.labelLine != null) return serieData.labelLine;
|
||||
else return serie.labelLine;
|
||||
}
|
||||
}
|
||||
|
||||
public static IconStyle GetIconStyle(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (serieData.iconStyle != null) return serieData.iconStyle;
|
||||
else return serie.iconStyle;
|
||||
}
|
||||
|
||||
public static SymbolStyle GetSerieSymbol(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.symbol != null) return serieData.symbol;
|
||||
else return serie.symbol;
|
||||
}
|
||||
|
||||
public static Color32 GetAreaColor(Serie serie, ThemeStyle theme, int index, bool highlight)
|
||||
{
|
||||
var areaStyle = serie.areaStyle;
|
||||
if (areaStyle == null || !areaStyle.show)
|
||||
return ColorUtil.clearColor32;
|
||||
var color = !ChartHelper.IsClearColor(areaStyle.color)
|
||||
? areaStyle.color : theme.GetColor(index);
|
||||
if (highlight)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(areaStyle.highlightColor))
|
||||
color = areaStyle.highlightColor;
|
||||
else
|
||||
color = ChartHelper.GetHighlightColor(color);
|
||||
}
|
||||
ChartHelper.SetColorOpacity(ref color, areaStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
|
||||
public static Color32 GetAreaToColor(Serie serie, ThemeStyle theme, int index, bool highlight)
|
||||
{
|
||||
var areaStyle = serie.areaStyle;
|
||||
if (areaStyle == null || !areaStyle.show)
|
||||
return ColorUtil.clearColor32;
|
||||
if (!ChartHelper.IsClearColor(areaStyle.toColor))
|
||||
{
|
||||
var color = areaStyle.toColor;
|
||||
if (highlight)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(areaStyle.highlightToColor)) color = areaStyle.highlightToColor;
|
||||
else color = ChartHelper.GetHighlightColor(color);
|
||||
}
|
||||
ChartHelper.SetColorOpacity(ref color, areaStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetAreaColor(serie, theme, index, highlight);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color32 GetLineColor(Serie serie, ThemeStyle theme, int index, bool highlight)
|
||||
{
|
||||
Color32 color = ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, null);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
|
||||
{
|
||||
color = itemStyleEmphasis.color;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
if (!ChartHelper.IsClearColor(serie.lineStyle.color)) color = serie.lineStyle.GetColor();
|
||||
else if (!ChartHelper.IsClearColor(serie.itemStyle.color)) color = serie.itemStyle.GetColor();
|
||||
if (ChartHelper.IsClearColor(color))
|
||||
{
|
||||
color = theme.GetColor(index);
|
||||
ChartHelper.SetColorOpacity(ref color, serie.lineStyle.opacity);
|
||||
}
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
return color;
|
||||
}
|
||||
|
||||
public static float GetSymbolBorder(Serie serie, SerieData serieData, ThemeStyle theme, bool highlight)
|
||||
{
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle != null && itemStyle.borderWidth != 0) return itemStyle.borderWidth;
|
||||
else return serie.lineStyle.GetWidth(theme.serie.lineWidth) * 2;
|
||||
}
|
||||
|
||||
public static float GetSymbolBorder(Serie serie, SerieData serieData, ThemeStyle theme, bool highlight, float defaultWidth)
|
||||
{
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle != null && itemStyle.borderWidth != 0) return itemStyle.borderWidth;
|
||||
else return defaultWidth;
|
||||
}
|
||||
|
||||
public static float[] GetSymbolCornerRadius(Serie serie, SerieData serieData, bool highlight)
|
||||
{
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle != null) return itemStyle.cornerRadius;
|
||||
else return null;
|
||||
}
|
||||
|
||||
public static string GetNumericFormatter(Serie serie, SerieData serieData, string defaultFormatter = null)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
|
||||
else return defaultFormatter;
|
||||
}
|
||||
|
||||
public static string GetItemFormatter(Serie serie, SerieData serieData, string defaultFormatter = null)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.itemFormatter)) return itemStyle.itemFormatter;
|
||||
else return defaultFormatter;
|
||||
}
|
||||
|
||||
public static string GetItemMarker(Serie serie, SerieData serieData, string defaultMarker = null)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.itemMarker)) return itemStyle.itemMarker;
|
||||
else return defaultMarker;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得指定维数的最大最小值
|
||||
/// </summary>
|
||||
/// <param name="dimension"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
public static void UpdateMinMaxData(Serie serie, int dimension, int ceilRate = 0, DataZoom dataZoom = null)
|
||||
{
|
||||
double min = 0, max = 0;
|
||||
GetMinMaxData(serie, dimension, out min, out max, dataZoom);
|
||||
if (ceilRate < 0)
|
||||
{
|
||||
serie.context.dataMin = min;
|
||||
serie.context.dataMax = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.dataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
|
||||
serie.context.dataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetAllMinMaxData(Serie serie, int ceilRate = 0, DataZoom dataZoom = null)
|
||||
{
|
||||
double min = 0, max = 0;
|
||||
GetMinMaxData(serie, out min, out max, dataZoom);
|
||||
if (ceilRate < 0)
|
||||
{
|
||||
serie.context.dataMin = min;
|
||||
serie.context.dataMax = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.dataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
|
||||
serie.context.dataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SerieData> emptyFilter = new List<SerieData>();
|
||||
/// <summary>
|
||||
/// 根据dataZoom更新数据列表缓存
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
public static void UpdateFilterData(Serie serie, DataZoom dataZoom)
|
||||
{
|
||||
if (dataZoom == null || !dataZoom.enable) return;
|
||||
if (dataZoom.IsContainsXAxis(serie.xAxisIndex))
|
||||
{
|
||||
if (dataZoom.IsXAxisIndexValue(serie.xAxisIndex))
|
||||
{
|
||||
double min = 0, max = 0;
|
||||
dataZoom.GetXAxisIndexValue(serie.xAxisIndex, out min, out max);
|
||||
UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateFilterData_Category(serie, dataZoom);
|
||||
}
|
||||
}
|
||||
else if (dataZoom.IsContainsYAxis(serie.yAxisIndex))
|
||||
{
|
||||
if (dataZoom.IsYAxisIndexValue(serie.yAxisIndex))
|
||||
{
|
||||
double min = 0, max = 0;
|
||||
dataZoom.GetYAxisIndexValue(serie.yAxisIndex, out min, out max);
|
||||
UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateFilterData_Category(serie, dataZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateFilterData_XAxisValue(Serie serie, DataZoom dataZoom, int dimension, double min, double max)
|
||||
{
|
||||
var data = serie.data;
|
||||
var startValue = min + (max - min) * dataZoom.start / 100;
|
||||
var endValue = min + (max - min) * dataZoom.end / 100;
|
||||
if (endValue < startValue) endValue = startValue;
|
||||
|
||||
if (startValue != serie.m_FilterStartValue || endValue != serie.m_FilterEndValue
|
||||
|| dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
|
||||
{
|
||||
serie.m_FilterStartValue = startValue;
|
||||
serie.m_FilterEndValue = endValue;
|
||||
serie.m_FilterMinShow = dataZoom.minShowNum;
|
||||
serie.m_NeedUpdateFilterData = false;
|
||||
|
||||
serie.m_FilterData.Clear();
|
||||
foreach (var serieData in data)
|
||||
{
|
||||
var value = serieData.GetData(dimension);
|
||||
if (value >= startValue && value <= endValue)
|
||||
{
|
||||
serie.m_FilterData.Add(serieData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (endValue == 0)
|
||||
{
|
||||
serie.m_FilterData = emptyFilter;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateFilterData_Category(Serie serie, DataZoom dataZoom)
|
||||
{
|
||||
var data = serie.data;
|
||||
var range = Mathf.RoundToInt(data.Count * (dataZoom.end - dataZoom.start) / 100);
|
||||
if (range <= 0) range = 1;
|
||||
int start = 0, end = 0;
|
||||
if (dataZoom.context.invert)
|
||||
{
|
||||
end = Mathf.CeilToInt(data.Count * dataZoom.end / 100);
|
||||
start = end - range;
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = Mathf.FloorToInt(data.Count * dataZoom.start / 100);
|
||||
end = start + range;
|
||||
if (end > data.Count) end = data.Count;
|
||||
}
|
||||
if (start != serie.m_FilterStart || end != serie.m_FilterEnd
|
||||
|| dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
|
||||
{
|
||||
serie.m_FilterStart = start;
|
||||
serie.m_FilterEnd = end;
|
||||
serie.m_FilterMinShow = dataZoom.minShowNum;
|
||||
serie.m_NeedUpdateFilterData = false;
|
||||
if (data.Count > 0)
|
||||
{
|
||||
if (range < dataZoom.minShowNum)
|
||||
{
|
||||
if (dataZoom.minShowNum > data.Count) range = data.Count;
|
||||
else range = dataZoom.minShowNum;
|
||||
}
|
||||
serie.m_FilterData = data.GetRange(start, range);
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.m_FilterData = data;
|
||||
}
|
||||
}
|
||||
else if (end == 0)
|
||||
{
|
||||
serie.m_FilterData = emptyFilter;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateSerieRuntimeFilterData(Serie serie, bool filterInvisible = true)
|
||||
{
|
||||
serie.context.sortedData.Clear();
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (!filterInvisible || (filterInvisible && serieData.show))
|
||||
serie.context.sortedData.Add(serieData);
|
||||
}
|
||||
switch (serie.dataSortType)
|
||||
{
|
||||
case SerieDataSortType.Ascending:
|
||||
serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2)
|
||||
{
|
||||
var value1 = data1.GetData(1);
|
||||
var value2 = data2.GetData(1);
|
||||
if (value1 == value2) return 0;
|
||||
else if (value1 > value2) return 1;
|
||||
else return -1;
|
||||
});
|
||||
break;
|
||||
case SerieDataSortType.Descending:
|
||||
serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2)
|
||||
{
|
||||
var value1 = data1.GetData(1);
|
||||
var value2 = data2.GetData(1);
|
||||
if (value1 == value2) return 0;
|
||||
else if (value1 > value2) return -1;
|
||||
else return 1;
|
||||
});
|
||||
break;
|
||||
case SerieDataSortType.None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static T CloneSerie<T>(Serie serie) where T : Serie
|
||||
{
|
||||
var newSerie = Activator.CreateInstance<T>();
|
||||
SerieHelper.CopySerie(serie, newSerie);
|
||||
return newSerie;
|
||||
}
|
||||
|
||||
public static void CopySerie(Serie oldSerie, Serie newSerie)
|
||||
{
|
||||
var fields = typeof(Serie).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (field.IsDefined(typeof(SerializeField)))
|
||||
{
|
||||
field.SetValue(newSerie, field.GetValue(oldSerie));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Helper/SerieHelper.cs.meta
Normal file
11
Runtime/Helper/SerieHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c031417514104eebb5bbd60dd1f90fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
265
Runtime/Helper/SerieLabelHelper.cs
Normal file
265
Runtime/Helper/SerieLabelHelper.cs
Normal file
@@ -0,0 +1,265 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class SerieLabelHelper
|
||||
{
|
||||
|
||||
public static Color GetLabelColor(Serie serie, ThemeStyle theme, int index)
|
||||
{
|
||||
if (serie.label != null && !ChartHelper.IsClearColor(serie.label.textStyle.color))
|
||||
{
|
||||
return serie.label.textStyle.color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return theme.GetColor(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ResetLabel(ChartText labelObject, LabelStyle label, ThemeStyle theme)
|
||||
{
|
||||
if (labelObject == null) return;
|
||||
labelObject.SetColor(!ChartHelper.IsClearColor(label.textStyle.color) ? label.textStyle.color :
|
||||
theme.common.textColor);
|
||||
labelObject.SetFontSize(label.textStyle.GetFontSize(theme.common));
|
||||
labelObject.SetFontStyle(label.textStyle.fontStyle);
|
||||
}
|
||||
|
||||
public static bool CanShowLabel(Serie serie, SerieData serieData, LabelStyle label, int dimesion)
|
||||
{
|
||||
return serie.show && serieData.context.canShowLabel && !serie.IsIgnoreValue(serieData, dimesion);
|
||||
}
|
||||
|
||||
public static string GetFormatterContent(Serie serie, SerieData serieData,
|
||||
double dataValue, double dataTotal, LabelStyle serieLabel, Color color)
|
||||
{
|
||||
if (serieLabel == null)
|
||||
{
|
||||
serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
}
|
||||
var numericFormatter = serieLabel == null ? "" : serieLabel.numericFormatter;
|
||||
var serieName = serie.serieName;
|
||||
var dataName = serieData != null ? serieData.name : null;
|
||||
if (serieLabel.formatterFunction != null)
|
||||
{
|
||||
return serieLabel.formatterFunction(serieData.index, dataValue);
|
||||
}
|
||||
if (string.IsNullOrEmpty(serieLabel.formatter))
|
||||
return ChartCached.NumberToStr(dataValue, numericFormatter);
|
||||
else
|
||||
{
|
||||
var content = serieLabel.formatter;
|
||||
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, dataValue,
|
||||
dataTotal, serieName, dataName, dataName, color);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetGaugeLabelText(Serie serie)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
if (serieData.labelObject == null) return;
|
||||
var label = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (label == null) return;
|
||||
var value = serieData.GetData(1);
|
||||
var total = serie.max;
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total, null, Color.clear);
|
||||
serieData.labelObject.SetText(content);
|
||||
serieData.labelObject.SetLabelPosition(serie.context.center + label.offset);
|
||||
if (!ChartHelper.IsClearColor(label.textStyle.color))
|
||||
{
|
||||
serieData.labelObject.label.SetColor(label.textStyle.color);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetRingLabelText(Serie serie, ThemeStyle theme)
|
||||
{
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.context.highlight);
|
||||
if (serieLabel != null && serieLabel.show && serieData.labelObject != null)
|
||||
{
|
||||
if (!serie.show || !serieData.show)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
continue;
|
||||
}
|
||||
var value = serieData.GetData(0);
|
||||
var total = serieData.GetData(1);
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total, null, Color.clear);
|
||||
serieData.SetLabelActive(true);
|
||||
serieData.labelObject.SetText(content);
|
||||
serieData.labelObject.SetTextColor(GetLabelColor(serie, theme, i));
|
||||
|
||||
if (serieLabel.position == LabelStyle.Position.Bottom)
|
||||
{
|
||||
var labelWidth = serieData.GetLabelWidth();
|
||||
if (serie.clockwise)
|
||||
serieData.labelObject.SetLabelPosition(serieData.context.labelPosition - new Vector3(labelWidth / 2, 0));
|
||||
else
|
||||
serieData.labelObject.SetLabelPosition(serieData.context.labelPosition + new Vector3(labelWidth / 2, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.labelObject.SetLabelPosition(serieData.context.labelPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetLiquidLabelText(Serie serie, ThemeStyle theme, int colorIndex)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.context.highlight);
|
||||
if (serieLabel.show && serieData.labelObject != null)
|
||||
{
|
||||
if (!serie.show || !serieData.show)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
return;
|
||||
}
|
||||
var value = serieData.GetData(1);
|
||||
var total = serie.max - serie.min;
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total, null, Color.clear);
|
||||
serieData.SetLabelActive(true);
|
||||
serieData.labelObject.SetText(content);
|
||||
serieData.labelObject.SetTextColor(GetLabelColor(serie, theme, colorIndex));
|
||||
serieData.labelObject.SetLabelPosition(serieData.context.labelPosition + serieLabel.offset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdatePieLabelPosition(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (serieData.labelObject == null) return;
|
||||
var currAngle = serieData.context.halfAngle;
|
||||
var currRad = currAngle * Mathf.Deg2Rad;
|
||||
var offsetRadius = serieData.context.offsetRadius;
|
||||
var insideRadius = serieData.context.insideRadius;
|
||||
var outsideRadius = serieData.context.outsideRadius;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||
switch (serieLabel.position)
|
||||
{
|
||||
case LabelStyle.Position.Center:
|
||||
serieData.context.labelPosition = serie.context.center;
|
||||
break;
|
||||
case LabelStyle.Position.Inside:
|
||||
var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2 + serieLabel.margin;
|
||||
var labelCenter = new Vector2(serie.context.center.x + labelRadius * Mathf.Sin(currRad),
|
||||
serie.context.center.y + labelRadius * Mathf.Cos(currRad));
|
||||
serieData.context.labelPosition = labelCenter;
|
||||
break;
|
||||
case LabelStyle.Position.Outside:
|
||||
if (labelLine != null && labelLine.lineType == LabelLine.LineType.HorizontalLine)
|
||||
{
|
||||
var radius1 = serie.context.outsideRadius;
|
||||
var radius3 = insideRadius + (outsideRadius - insideRadius) / 2;
|
||||
var currSin = Mathf.Sin(currRad);
|
||||
var currCos = Mathf.Cos(currRad);
|
||||
var pos0 = new Vector3(serie.context.center.x + radius3 * currSin, serie.context.center.y + radius3 * currCos);
|
||||
if (currAngle > 180)
|
||||
{
|
||||
currSin = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
||||
currCos = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
||||
}
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
||||
r4 += labelLine.lineLength1 + labelLine.lineWidth * 4;
|
||||
r4 += serieData.labelObject.label.GetPreferredWidth() / 2;
|
||||
serieData.context.labelPosition = pos0 + (currAngle > 180 ? Vector3.left : Vector3.right) * r4;
|
||||
}
|
||||
else
|
||||
{
|
||||
labelRadius = serie.context.outsideRadius + (labelLine == null ? 0 : labelLine.lineLength1);
|
||||
labelCenter = new Vector2(serie.context.center.x + labelRadius * Mathf.Sin(currRad),
|
||||
serie.context.center.y + labelRadius * Mathf.Cos(currRad));
|
||||
serieData.context.labelPosition = labelCenter;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AvoidLabelOverlap(Serie serie, ComponentTheme theme)
|
||||
{
|
||||
if (!serie.avoidLabelOverlap) return;
|
||||
var lastCheckPos = Vector3.zero;
|
||||
var data = serie.data;
|
||||
var splitCount = 0;
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
if (serieData.context.labelPosition.x != 0 && serieData.context.labelPosition.x < serie.context.center.x)
|
||||
{
|
||||
splitCount = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int n = 0; n < splitCount; n++)
|
||||
{
|
||||
CheckSerieDataLabel(serie, data[n], false, theme, ref lastCheckPos);
|
||||
}
|
||||
lastCheckPos = Vector3.zero;
|
||||
for (int n = data.Count - 1; n >= splitCount; n--)
|
||||
{
|
||||
CheckSerieDataLabel(serie, data[n], true, theme, ref lastCheckPos);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckSerieDataLabel(Serie serie, SerieData serieData, bool isLeft, ComponentTheme theme,
|
||||
ref Vector3 lastCheckPos)
|
||||
{
|
||||
if (!serieData.context.canShowLabel)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
return;
|
||||
}
|
||||
if (!serieData.show) return;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||
var fontSize = serieLabel.textStyle.GetFontSize(theme);
|
||||
if (!serieLabel.show) return;
|
||||
if (serieLabel.position != LabelStyle.Position.Outside) return;
|
||||
if (lastCheckPos == Vector3.zero)
|
||||
{
|
||||
lastCheckPos = serieData.context.labelPosition;
|
||||
}
|
||||
else if (serieData.context.labelPosition.x != 0)
|
||||
{
|
||||
if (lastCheckPos.y - serieData.context.labelPosition.y < fontSize)
|
||||
{
|
||||
var labelRadius = serie.context.outsideRadius + labelLine.lineLength1;
|
||||
var y1 = lastCheckPos.y - fontSize;
|
||||
var cy = serie.context.center.y;
|
||||
var diff = Mathf.Abs(y1 - cy);
|
||||
var diffX = labelRadius * labelRadius - diff * diff;
|
||||
diffX = diffX <= 0 ? 0 : diffX;
|
||||
var x1 = serie.context.center.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
|
||||
serieData.context.labelPosition = new Vector3(x1, y1);
|
||||
}
|
||||
lastCheckPos = serieData.context.labelPosition;
|
||||
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel, labelLine));
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3 GetRealLabelPosition(SerieData serieData, LabelStyle label, LabelLine labelLine)
|
||||
{
|
||||
if (label.position == LabelStyle.Position.Outside && labelLine.lineType != LabelLine.LineType.HorizontalLine)
|
||||
{
|
||||
var currAngle = serieData.context.halfAngle;
|
||||
var offset = labelLine.lineLength2 + serieData.labelObject.GetLabelWidth() / 2;
|
||||
if (currAngle > 180)
|
||||
return serieData.context.labelPosition + new Vector3(-offset, 0, 0);
|
||||
else
|
||||
return serieData.context.labelPosition + new Vector3(offset, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return serieData.context.labelPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Helper/SerieLabelHelper.cs.meta
Normal file
11
Runtime/Helper/SerieLabelHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b81cddd3452545748563f9c6ea9be69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
493
Runtime/Helper/SeriesHelper.cs
Normal file
493
Runtime/Helper/SeriesHelper.cs
Normal file
@@ -0,0 +1,493 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class SeriesHelper
|
||||
{
|
||||
|
||||
public static bool IsLegalLegendName(string name)
|
||||
{
|
||||
int numName = -1;
|
||||
if (int.TryParse(name, out numName))
|
||||
{
|
||||
if (numName >= 0 && numName < 100) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<string> GetLegalSerieNameList(List<Serie> series)
|
||||
{
|
||||
var list = new List<string>();
|
||||
for (int n = 0; n < series.Count; n++)
|
||||
{
|
||||
var serie = series[n];
|
||||
if (serie.useDataNameForColor)
|
||||
{
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var dataName = serie.data[i].name;
|
||||
if (!string.IsNullOrEmpty(dataName) && IsLegalLegendName(dataName) && !list.Contains(dataName))
|
||||
list.Add(dataName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(serie.serieName) && !list.Contains(serie.serieName) && IsLegalLegendName(serie.serieName))
|
||||
list.Add(serie.serieName);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得所有系列名,不包含空名字。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static void UpdateSerieNameList(BaseChart chart, ref List<string> serieNameList)
|
||||
{
|
||||
serieNameList.Clear();
|
||||
for (int n = 0; n < chart.series.Count; n++)
|
||||
{
|
||||
var serie = chart.series[n];
|
||||
if (serie.useDataNameForColor)
|
||||
{
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
if (serie is Pie && serie.IsIgnoreValue(serie.data[i])) continue;
|
||||
if (string.IsNullOrEmpty(serie.data[i].name))
|
||||
serieNameList.Add(ChartCached.IntToStr(i));
|
||||
else if (!serieNameList.Contains(serie.data[i].name))
|
||||
serieNameList.Add(serie.data[i].name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(serie.serieName))
|
||||
serieNameList.Add(ChartCached.IntToStr(n));
|
||||
else if (!serieNameList.Contains(serie.serieName))
|
||||
serieNameList.Add(serie.serieName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Color GetNameColor(BaseChart chart, int index, string name)
|
||||
{
|
||||
Serie destSerie = null;
|
||||
SerieData destSerieData = null;
|
||||
var series = chart.series;
|
||||
for (int n = 0; n < series.Count; n++)
|
||||
{
|
||||
var serie = series[n];
|
||||
if (serie.useDataNameForColor)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
if (name.Equals(serie.data[i].name))
|
||||
{
|
||||
destSerie = serie;
|
||||
destSerieData = serie.data[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name.Equals(serie.serieName))
|
||||
{
|
||||
destSerie = serie;
|
||||
destSerieData = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SerieHelper.GetItemColor(destSerie, destSerieData, chart.theme, index, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同堆叠的serie是否有渐变色的。
|
||||
/// </summary>
|
||||
/// <param name="stack"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAnyGradientSerie(List<Serie> series, string stack)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stack)) return false;
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.show && serie.areaStyle != null && serie.areaStyle.show && stack.Equals(serie.stack))
|
||||
{
|
||||
if (!ChartHelper.IsValueEqualsColor(serie.areaStyle.color, serie.areaStyle.toColor)
|
||||
&& !ChartHelper.IsClearColor(serie.areaStyle.toColor))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否有需裁剪的serie。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsAnyClipSerie(List<Serie> series)
|
||||
{
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.clip) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsAnyUpdateAnimationSerie(List<Serie> series)
|
||||
{
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.animation.enable && serie.animation.dataChangeEnable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得上一个同堆叠且显示的serie。
|
||||
/// </summary>
|
||||
/// <param name="serie"></param>
|
||||
/// <returns></returns>
|
||||
public static Serie GetLastStackSerie(List<Serie> series, Serie serie)
|
||||
{
|
||||
if (serie == null || string.IsNullOrEmpty(serie.stack)) return null;
|
||||
for (int i = serie.index - 1; i >= 0; i--)
|
||||
{
|
||||
var temp = series[i];
|
||||
if (temp.show && serie.stack.Equals(temp.stack)) return temp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得上一个同堆叠且显示的serie。
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public static Serie GetLastStackSerie(List<Serie> series, int index)
|
||||
{
|
||||
var serie = series[index];
|
||||
return GetLastStackSerie(series, serie);
|
||||
}
|
||||
|
||||
public static Serie GetSerieByVesselIndex(List<Serie> series, int vesselIndex)
|
||||
{
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.vesselIndex == vesselIndex) return serie;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HashSet<string> _setForStack = new HashSet<string>();
|
||||
/// <summary>
|
||||
/// 是否由数据堆叠
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsStack(List<Serie> series)
|
||||
{
|
||||
_setForStack.Clear();
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serie.stack)) continue;
|
||||
if (_setForStack.Contains(serie.stack)) return true;
|
||||
_setForStack.Add(serie.stack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否堆叠
|
||||
/// </summary>
|
||||
/// <param name="stackName"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsStack<T>(List<Serie> series, string stackName) where T : Serie
|
||||
{
|
||||
if (string.IsNullOrEmpty(stackName)) return false;
|
||||
int count = 0;
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.show && serie is T)
|
||||
{
|
||||
if (stackName.Equals(serie.stack)) count++;
|
||||
if (count >= 2) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否时百分比堆叠
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPercentStack<T>(List<Serie> series) where T : Serie
|
||||
{
|
||||
int count = 0;
|
||||
bool isPercentStack = false;
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.show && serie is T)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(serie.stack))
|
||||
{
|
||||
count++;
|
||||
if (serie.barPercentStack) isPercentStack = true;
|
||||
}
|
||||
if (count >= 2 && isPercentStack) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否时百分比堆叠
|
||||
/// </summary>
|
||||
/// <param name="stackName"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPercentStack<T>(List<Serie> series, string stackName) where T : Serie
|
||||
{
|
||||
if (string.IsNullOrEmpty(stackName)) return false;
|
||||
int count = 0;
|
||||
bool isPercentStack = false;
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.show && serie is T)
|
||||
{
|
||||
if (stackName.Equals(serie.stack))
|
||||
{
|
||||
count++;
|
||||
if (serie.barPercentStack) isPercentStack = true;
|
||||
}
|
||||
if (count >= 2 && isPercentStack) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Dictionary<string, int> sets = new Dictionary<string, int>();
|
||||
/// <summary>
|
||||
/// 获得堆叠系列列表
|
||||
/// </summary>
|
||||
/// <param name="Dictionary<int"></param>
|
||||
/// <param name="stackSeries"></param>
|
||||
public static void GetStackSeries(List<Serie> series, ref Dictionary<int, List<Serie>> stackSeries)
|
||||
{
|
||||
int count = 0;
|
||||
var serieCount = series.Count;
|
||||
sets.Clear();
|
||||
if (stackSeries == null)
|
||||
{
|
||||
stackSeries = new Dictionary<int, List<Serie>>(serieCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kv in stackSeries)
|
||||
{
|
||||
kv.Value.Clear();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < serieCount; i++)
|
||||
{
|
||||
var serie = series[i];
|
||||
serie.index = i;
|
||||
if (string.IsNullOrEmpty(serie.stack))
|
||||
{
|
||||
if (!stackSeries.ContainsKey(count))
|
||||
stackSeries[count] = new List<Serie>(serieCount);
|
||||
stackSeries[count].Add(serie);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sets.ContainsKey(serie.stack))
|
||||
{
|
||||
sets.Add(serie.stack, count);
|
||||
if (!stackSeries.ContainsKey(count))
|
||||
stackSeries[count] = new List<Serie>(serieCount);
|
||||
stackSeries[count].Add(serie);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int stackIndex = sets[serie.stack];
|
||||
stackSeries[stackIndex].Add(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateStackDataList(List<Serie> series, Serie currSerie, DataZoom dataZoom, List<List<SerieData>> dataList)
|
||||
{
|
||||
dataList.Clear();
|
||||
for (int i = 0; i <= currSerie.index; i++)
|
||||
{
|
||||
var serie = series[i];
|
||||
if (serie.GetType() == currSerie.GetType() && ChartHelper.IsValueEqualsString(serie.stack, currSerie.stack))
|
||||
{
|
||||
dataList.Add(serie.GetDataList(dataZoom));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得维度X的最大最小值
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <param name="axisIndex"></param>
|
||||
/// <param name="minVaule"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
public static void GetXMinMaxValue(List<Serie> series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
|
||||
bool inverse, out double minVaule, out double maxValue, bool isPolar = false)
|
||||
{
|
||||
GetMinMaxValue(series, dataZoom, axisIndex, isValueAxis, inverse, false, out minVaule, out maxValue, isPolar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得维度Y的最大最小值
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <param name="axisIndex"></param>
|
||||
/// <param name="minVaule"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
public static void GetYMinMaxValue(List<Serie> series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
|
||||
bool inverse, out double minVaule, out double maxValue, bool isPolar = false)
|
||||
{
|
||||
GetMinMaxValue(series, dataZoom, axisIndex, isValueAxis, inverse, true, out minVaule, out maxValue, isPolar);
|
||||
}
|
||||
|
||||
private static Dictionary<int, List<Serie>> _stackSeriesForMinMax = new Dictionary<int, List<Serie>>();
|
||||
private static Dictionary<int, double> _serieTotalValueForMinMax = new Dictionary<int, double>();
|
||||
public static void GetMinMaxValue(List<Serie> series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
|
||||
bool inverse, bool yValue, out double minVaule, out double maxValue, bool isPolar = false)
|
||||
{
|
||||
double min = double.MaxValue;
|
||||
double max = double.MinValue;
|
||||
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(series);
|
||||
if (!SeriesHelper.IsStack(series) || (isValueAxis && !yValue))
|
||||
{
|
||||
for (int i = 0; i < series.Count; i++)
|
||||
{
|
||||
var serie = series[i];
|
||||
if ((isPolar && serie.polarIndex != axisIndex)
|
||||
|| (!isPolar && serie.yAxisIndex != axisIndex)
|
||||
|| !serie.show) continue;
|
||||
if (isPercentStack && SeriesHelper.IsPercentStack<Bar>(series, serie.serieName))
|
||||
{
|
||||
if (100 > max) max = 100;
|
||||
if (0 < min) min = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
foreach (var data in showData)
|
||||
{
|
||||
|
||||
if (serie is Candlestick)
|
||||
{
|
||||
var dataMin = data.GetMinData(inverse);
|
||||
var dataMax = data.GetMaxData(inverse);
|
||||
if (dataMax > max) max = dataMax;
|
||||
if (dataMin < min) min = dataMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
var currData = data.GetData(yValue ? 1 : 0, inverse);
|
||||
if (!serie.IsIgnoreValue(currData))
|
||||
{
|
||||
if (currData > max) max = currData;
|
||||
if (currData < min) min = currData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SeriesHelper.GetStackSeries(series, ref _stackSeriesForMinMax);
|
||||
foreach (var ss in _stackSeriesForMinMax)
|
||||
{
|
||||
_serieTotalValueForMinMax.Clear();
|
||||
for (int i = 0; i < ss.Value.Count; i++)
|
||||
{
|
||||
var serie = ss.Value[i];
|
||||
if ((isPolar && serie.polarIndex != axisIndex)
|
||||
|| (!isPolar && serie.yAxisIndex != axisIndex)
|
||||
|| !serie.show) continue;
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
if (SeriesHelper.IsPercentStack<Bar>(series, serie.stack))
|
||||
{
|
||||
for (int j = 0; j < showData.Count; j++)
|
||||
{
|
||||
_serieTotalValueForMinMax[j] = 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < showData.Count; j++)
|
||||
{
|
||||
if (!_serieTotalValueForMinMax.ContainsKey(j))
|
||||
_serieTotalValueForMinMax[j] = 0;
|
||||
double currData = 0;
|
||||
if (serie is Candlestick)
|
||||
{
|
||||
currData = showData[j].GetMaxData(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
currData = yValue ? showData[j].GetData(1) : showData[j].GetData(0);
|
||||
}
|
||||
if (inverse) currData = -currData;
|
||||
if (!serie.IsIgnoreValue(currData))
|
||||
_serieTotalValueForMinMax[j] = _serieTotalValueForMinMax[j] + currData;
|
||||
}
|
||||
}
|
||||
}
|
||||
double tmax = double.MinValue;
|
||||
double tmin = double.MaxValue;
|
||||
foreach (var tt in _serieTotalValueForMinMax)
|
||||
{
|
||||
if (tt.Value > tmax) tmax = tt.Value;
|
||||
if (tt.Value < tmin) tmin = tt.Value;
|
||||
}
|
||||
if (tmax > max) max = tmax;
|
||||
if (tmin < min) min = tmin;
|
||||
}
|
||||
}
|
||||
if (max == double.MinValue && min == double.MaxValue)
|
||||
{
|
||||
minVaule = 0;
|
||||
maxValue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
minVaule = min > 1 ? Math.Floor(min) : min;
|
||||
maxValue = max > 1 ? Math.Ceiling(max) : max;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetMaxSerieDataCount(List<Serie> series)
|
||||
{
|
||||
int max = 0;
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.dataCount > max) max = serie.dataCount;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Helper/SeriesHelper.cs.meta
Normal file
11
Runtime/Helper/SeriesHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96a06a5949772464da15c44ae2ad400d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user