3.0 - unitypackage

This commit is contained in:
monitor1394
2022-01-05 21:40:48 +08:00
parent c160867765
commit 228a4b2840
846 changed files with 105 additions and 467693 deletions

View 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");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09a50ff0a7fdb4174b4dc2d28fc08b6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fddcb81df44148ed86496564b120261
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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));
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c031417514104eebb5bbd60dd1f90fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0b81cddd3452545748563f9c6ea9be69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96a06a5949772464da15c44ae2ad400d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: