Files
XCharts/Runtime/Component/Sub/SerieData.cs

455 lines
17 KiB
C#
Raw Normal View History

2021-01-11 08:54:28 +08:00
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
2019-07-28 00:44:53 +08:00
using UnityEngine;
using UnityEngine.UI;
2019-07-28 00:44:53 +08:00
namespace XCharts
{
/// <summary>
/// A data item of serie.
/// 系列中的一个数据项。可存储数据名和1-n维的数据。
2019-07-28 00:44:53 +08:00
/// </summary>
[System.Serializable]
2019-10-14 18:13:08 +08:00
public class SerieData : SubComponent
2019-07-28 00:44:53 +08:00
{
[SerializeField] private int m_Index;
[SerializeField] private int m_ParentIndex = -1;
2019-07-28 00:44:53 +08:00
[SerializeField] private string m_Name;
[SerializeField] private string m_Id;
2019-07-28 00:44:53 +08:00
[SerializeField] private bool m_Selected;
[SerializeField] private bool m_Ignore = false;
[SerializeField] private float m_Radius;
[SerializeField] private bool m_EnableIconStyle = false;
[SerializeField] private IconStyle m_IconStyle = new IconStyle();
2019-11-30 21:24:04 +08:00
[SerializeField] private bool m_EnableLabel = false;
[SerializeField] private SerieLabel m_Label = new SerieLabel();
[SerializeField] private bool m_EnableItemStyle = false;
[SerializeField] private ItemStyle m_ItemStyle = new ItemStyle();
[SerializeField] private bool m_EnableEmphasis = false;
[SerializeField] private Emphasis m_Emphasis = new Emphasis();
[SerializeField] private bool m_EnableSymbol = false;
[SerializeField] private SerieSymbol m_Symbol = new SerieSymbol();
[SerializeField] private List<double> m_Data = new List<double>();
[SerializeField] private List<int> m_Children = new List<int>();
2019-07-28 00:44:53 +08:00
2021-01-11 08:54:28 +08:00
public ChartLabel labelObject { get; set; }
2019-07-28 00:44:53 +08:00
private bool m_Show = true;
private float m_RtPieOutsideRadius;
2019-07-28 00:44:53 +08:00
public int index { get { return m_Index; } set { m_Index = value; } }
public int parentIndex { get { return m_ParentIndex; } set { m_ParentIndex = value; } }
2019-07-28 00:44:53 +08:00
/// <summary>
/// the name of data item.
/// 数据项名称。
2019-07-28 00:44:53 +08:00
/// </summary>
public string name { get { return m_Name; } set { m_Name = value; } }
/// <summary>
2021-10-24 19:23:17 +08:00
/// 数据项的唯一id。唯一id不是必须设置的。
/// </summary>
public string id { get { return m_Id; } set { m_Id = value; } }
2021-10-24 19:23:17 +08:00
/// <summary>
/// 数据项图例名称。当数据项名称不为空时图例名称即为系列名称反之则为索引index。
/// </summary>
/// <value></value>
public string legendName { get { return string.IsNullOrEmpty(name) ? ChartCached.IntToStr(index) : name; } }
/// <summary>
/// 自定义半径。可用在饼图中自定义某个数据项的半径。
/// </summary>
public float radius { get { return m_Radius; } set { m_Radius = value; } }
/// <summary>
/// Whether the data item is selected.
/// 该数据项是否被选中。
2019-07-28 00:44:53 +08:00
/// </summary>
public bool selected { get { return m_Selected; } set { m_Selected = value; } }
/// <summary>
/// 是否启用单个数据项的图标设置。
/// </summary>
public bool enableIconStyle { get { return m_EnableIconStyle; } set { m_EnableIconStyle = value; } }
/// <summary>
/// the icon of data.
/// 数据项图标样式。
/// </summary>
public IconStyle iconStyle { get { return m_IconStyle; } set { m_IconStyle = value; } }
2019-07-28 00:44:53 +08:00
/// <summary>
2019-11-30 21:24:04 +08:00
/// 是否启用单个数据项的标签设置。
/// </summary>
public bool enableLabel { get { return m_EnableLabel; } set { m_EnableLabel = value; } }
/// <summary>
/// 单个数据项的标签设置。
/// </summary>
public SerieLabel label { get { return m_Label; } set { m_Label = value; } }
/// <summary>
/// 是否启用单个数据项的样式。
/// </summary>
public bool enableItemStyle { get { return m_EnableItemStyle; } set { m_EnableItemStyle = value; } }
/// <summary>
/// 单个数据项的样式设置。
/// </summary>
public ItemStyle itemStyle { get { return m_ItemStyle; } set { m_ItemStyle = value; } }
/// <summary>
/// 是否启用单个数据项的高亮样式。
/// </summary>
public bool enableEmphasis { get { return m_EnableEmphasis; } set { m_EnableEmphasis = value; } }
/// <summary>
/// 单个数据项的高亮样式设置。
/// </summary>
public Emphasis emphasis { get { return m_Emphasis; } set { m_Emphasis = value; } }
/// <summary>
/// 是否启用单个数据项的标记设置。
/// </summary>
public bool enableSymbol { get { return m_EnableSymbol; } set { m_EnableSymbol = value; } }
/// <summary>
/// 单个数据项的标记设置。
/// </summary>
public SerieSymbol symbol { get { return m_Symbol; } set { m_Symbol = value; } }
/// <summary>
/// 是否忽略数据。当为 true 时,数据不进行绘制。
/// </summary>
public bool ignore
{
get { return m_Ignore; }
set { if (PropertyUtil.SetStruct(ref m_Ignore, value)) SetVerticesDirty(); }
}
/// <summary>
/// An arbitrary dimension data list of data item.
/// 可指定任意维数的数值列表。
2019-07-28 00:44:53 +08:00
/// </summary>
public List<double> data { get { return m_Data; } set { m_Data = value; } }
public List<int> children { get { return m_Children; } set { m_Children = value; } }
2019-07-28 00:44:53 +08:00
/// <summary>
/// [default:true] Whether the data item is showed.
/// 该数据项是否要显示。
2019-07-28 00:44:53 +08:00
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// Whether the data item is highlighted.
/// 该数据项是否被高亮,一般由鼠标悬停或图例悬停触发高亮。
2019-07-28 00:44:53 +08:00
/// </summary>
public bool highlighted { get; set; }
public Vector3 labelPosition { get; set; }
private bool m_CanShowLabel = true;
/// <summary>
/// 是否可以显示Label
/// </summary>
2019-10-14 18:23:28 +08:00
public bool canShowLabel { get { return m_CanShowLabel; } set { m_CanShowLabel = value; } }
/// <summary>
/// 饼图数据项的开始角度(运行时自动计算)
/// </summary>
2022-03-16 07:43:46 +08:00
public float runtimePieStartAngle { get; set; }
/// <summary>
/// 饼图数据项的结束角度(运行时自动计算)
/// </summary>
2022-03-16 07:43:46 +08:00
public float runtimePieToAngle { get; set; }
/// <summary>
/// 饼图数据项的一半时的角度(运行时自动计算)
/// </summary>
2022-03-16 07:43:46 +08:00
public float runtimePieHalfAngle { get; set; }
/// <summary>
/// 饼图数据项的当前角度(运行时自动计算)
/// </summary>
2022-03-16 07:43:46 +08:00
public float runtimePieCurrAngle { get; set; }
/// <summary>
/// 饼图数据项的内半径
/// </summary>
2022-03-16 07:43:46 +08:00
public float runtimePieInsideRadius { get; set; }
/// <summary>
/// 饼图数据项的外半径
/// </summary>
public float runtimePieOutsideRadius
{
get
{
if (radius > 0) return radius;
else return m_RtPieOutsideRadius;
}
2022-03-16 07:43:46 +08:00
set
{
m_RtPieOutsideRadius = value;
}
}
/// <summary>
/// 饼图数据项的偏移半径
/// </summary>
2022-03-16 07:43:46 +08:00
public float runtimePieOffsetRadius { get; set; }
2021-04-22 18:55:56 +08:00
public Vector3 runtimePosition { get; set; }
2021-03-25 12:55:52 +08:00
/// <summary>
/// 绘制区域。
/// </summary>
public Rect runtimeRect { get; set; }
2021-10-24 19:23:17 +08:00
public Rect runtimeSubRect { get; set; }
public int runtimeLevel { get; set; }
public SerieData runtimeParent { get; set; }
public Color32 runtimeColor { get; set; }
public double runtimeArea { get; set; }
public float runtimeAngle { get; set; }
public Vector3 runtiemPieOffsetCenter { get; set; }
public float runtimeStackHig { get; set; }
public Image runtimeSymbol { get; set; }
public List<SerieData> runtimeChildren { get { return m_RuntimeChildren; } }
private List<double> m_PreviousData = new List<double>();
2019-12-03 07:49:37 +08:00
private List<float> m_DataUpdateTime = new List<float>();
private List<bool> m_DataUpdateFlag = new List<bool>();
2021-05-29 22:07:09 +08:00
private List<Vector2> m_PolygonPoints = new List<Vector2>();
[System.NonSerialized]
private List<SerieData> m_RuntimeChildren = new List<SerieData>();
2019-11-30 21:24:04 +08:00
public void Reset()
2020-05-09 09:42:41 +08:00
{
index = 0;
m_ParentIndex = -1;
labelObject = null;
highlighted = false;
2020-05-09 09:42:41 +08:00
m_Name = string.Empty;
m_Show = true;
2020-05-09 09:42:41 +08:00
m_Selected = false;
m_CanShowLabel = true;
m_EnableIconStyle = false;
m_EnableSymbol = false;
m_EnableLabel = false;
m_EnableEmphasis = false;
m_EnableItemStyle = false;
2020-05-09 09:42:41 +08:00
m_Radius = 0;
m_Data.Clear();
m_PreviousData.Clear();
m_PolygonPoints.Clear();
m_RuntimeChildren.Clear();
2020-05-09 09:42:41 +08:00
m_DataUpdateTime.Clear();
m_DataUpdateFlag.Clear();
m_IconStyle.Reset();
m_Label.Reset();
m_ItemStyle.Reset();
m_Emphasis.Reset();
2020-05-09 09:42:41 +08:00
}
public double GetData(int index, bool inverse = false)
{
2019-11-30 21:24:04 +08:00
if (index >= 0 && index < m_Data.Count)
{
return inverse ? -m_Data[index] : m_Data[index];
2019-11-30 21:24:04 +08:00
}
else return 0;
}
2019-08-16 00:13:01 +08:00
public double GetData(int index, double min, double max)
2021-05-22 15:29:55 +08:00
{
if (index >= 0 && index < m_Data.Count)
{
var value = m_Data[index];
if (value < min) return min;
else if (value > max) return max;
else return value;
}
else return 0;
}
public double GetPreviousData(int index, bool inverse = false)
2019-12-03 07:49:37 +08:00
{
2020-03-08 10:47:48 +08:00
if (index >= 0 && index < m_PreviousData.Count)
2019-12-03 07:49:37 +08:00
{
return inverse ? -m_PreviousData[index] : m_PreviousData[index];
2019-12-03 07:49:37 +08:00
}
else return 0;
}
public double GetFirstData(float animationDuration = 500f)
2020-03-08 10:47:48 +08:00
{
if (m_Data.Count > 0) return GetCurrData(0, animationDuration);
return 0;
}
public double GetLastData()
2020-03-08 10:47:48 +08:00
{
if (m_Data.Count > 0) return m_Data[m_Data.Count - 1];
return 0;
}
public double GetCurrData(int index, float animationDuration = 500f, bool inverse = false)
{
return GetCurrData(index, animationDuration, inverse, 0, 0);
}
public double GetCurrData(int index, float animationDuration, bool inverse, double min, double max)
2019-11-30 21:24:04 +08:00
{
2019-12-03 07:49:37 +08:00
if (index < m_DataUpdateFlag.Count && m_DataUpdateFlag[index] && animationDuration > 0)
2019-11-30 21:24:04 +08:00
{
2019-12-03 07:49:37 +08:00
var time = Time.time - m_DataUpdateTime[index];
2019-11-30 21:24:04 +08:00
var total = animationDuration / 1000;
var rate = time / total;
if (rate > 1) rate = 1;
if (rate < 1)
2019-11-30 21:24:04 +08:00
{
2019-12-03 07:49:37 +08:00
CheckLastData();
var curr = MathUtil.Lerp(GetPreviousData(index), GetData(index), rate);
if (min != 0 || max != 0)
{
if (inverse)
{
var temp = min;
min = -max;
max = -temp;
}
var pre = m_PreviousData[index];
if (pre < min)
{
m_PreviousData[index] = min;
curr = min;
}
else if (pre > max)
{
m_PreviousData[index] = max;
curr = max;
}
}
curr = inverse ? -curr : curr;
2019-11-30 21:24:04 +08:00
return curr;
}
else
{
2019-12-03 07:49:37 +08:00
m_DataUpdateFlag[index] = false;
return GetData(index, inverse);
2019-11-30 21:24:04 +08:00
}
}
else
{
return GetData(index, inverse);
2019-11-30 21:24:04 +08:00
}
}
/// <summary>
/// the maxinum value.
/// 最大值。
/// </summary>
public double GetMaxData(bool inverse = false)
{
if (m_Data.Count == 0) return 0;
var temp = double.MinValue;
for (int i = 0; i < m_Data.Count; i++)
{
var value = GetData(i, inverse);
if (value > temp) temp = value;
}
return temp;
}
/// <summary>
/// the mininum value.
/// 最小值。
/// </summary>
public double GetMinData(bool inverse = false)
{
if (m_Data.Count == 0) return 0;
var temp = double.MaxValue;
for (int i = 0; i < m_Data.Count; i++)
{
var value = GetData(i, inverse);
if (value < temp) temp = value;
}
return temp;
}
public bool UpdateData(int dimension, double value, bool updateAnimation, float animationDuration = 500f)
2019-11-30 21:24:04 +08:00
{
2019-12-03 07:49:37 +08:00
if (dimension >= 0 && dimension < data.Count)
{
CheckLastData();
m_PreviousData[dimension] = GetCurrData(dimension, animationDuration);
//m_PreviousData[dimension] = data[dimension];;
2019-12-03 07:49:37 +08:00
m_DataUpdateTime[dimension] = Time.time;
m_DataUpdateFlag[dimension] = updateAnimation;
2019-12-03 07:49:37 +08:00
data[dimension] = value;
return true;
2019-12-03 07:49:37 +08:00
}
return false;
2019-11-30 21:24:04 +08:00
}
2021-10-24 19:23:17 +08:00
public bool UpdateData(int dimension, double value)
{
if (dimension >= 0 && dimension < data.Count)
{
data[dimension] = value;
return true;
}
return false;
}
2019-12-03 07:49:37 +08:00
private void CheckLastData()
2019-11-30 21:24:04 +08:00
{
2020-03-08 10:47:48 +08:00
if (m_PreviousData.Count != m_Data.Count)
2019-11-30 21:24:04 +08:00
{
2020-03-08 10:47:48 +08:00
m_PreviousData.Clear();
2019-12-20 09:17:15 +08:00
m_DataUpdateTime.Clear();
m_DataUpdateFlag.Clear();
2019-12-03 07:49:37 +08:00
for (int i = 0; i < m_Data.Count; i++)
2019-11-30 21:24:04 +08:00
{
2020-03-08 10:47:48 +08:00
m_PreviousData.Add(m_Data[i]);
2019-12-03 07:49:37 +08:00
m_DataUpdateTime.Add(Time.time);
m_DataUpdateFlag.Add(false);
2019-11-30 21:24:04 +08:00
}
}
}
public bool IsDataChanged()
{
2019-12-03 07:49:37 +08:00
foreach (var b in m_DataUpdateFlag)
if (b) return true;
return false;
2019-11-30 21:24:04 +08:00
}
public float GetLabelWidth()
{
if (labelObject != null) return labelObject.GetLabelWidth();
else return 0;
}
public float GetLabelHeight()
{
if (labelObject != null) return labelObject.GetLabelHeight();
return 0;
}
public void SetLabelActive(bool flag)
2019-11-30 21:24:04 +08:00
{
if (labelObject != null) labelObject.SetLabelActive(flag);
2019-11-30 21:24:04 +08:00
}
public void SetIconActive(bool flag)
{
if (labelObject != null) labelObject.SetIconActive(flag);
}
2021-05-29 22:07:09 +08:00
public void SetPolygon(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
{
m_PolygonPoints.Clear();
m_PolygonPoints.Add(p1);
m_PolygonPoints.Add(p2);
m_PolygonPoints.Add(p3);
m_PolygonPoints.Add(p4);
}
public bool IsInPolygon(Vector2 p)
{
if (m_PolygonPoints.Count == 0) return false;
var inside = false;
var j = m_PolygonPoints.Count - 1;
for (int i = 0; i < m_PolygonPoints.Count; j = i++)
{
var pi = m_PolygonPoints[i];
var pj = m_PolygonPoints[j];
if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
(p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
inside = !inside;
}
return inside;
}
2019-07-28 00:44:53 +08:00
}
}