增加GaugeChart仪表盘

This commit is contained in:
monitor1394
2019-11-30 21:24:04 +08:00
parent 05d2a01103
commit e57a1a7a1c
52 changed files with 2673 additions and 338 deletions

View File

@@ -208,12 +208,52 @@ namespace XCharts
/// the current minimun value.
/// 当前最小值。
/// </summary>
public float runtimeMinValue { get; internal set; }
public float runtimeMinValue
{
get { return m_RuntimeMinValue; }
internal set
{
if (value != m_RuntimeMinValue)
{
if (m_RuntimeMinValueFirstChanged)
{
m_RuntimeMinValueFirstChanged = false;
}
else
{
m_RuntimeLastMinValue = m_RuntimeMinValue;
m_RuntimeMinValueChanged = true;
m_RuntimeMinValueUpdateTime = Time.time;
}
m_RuntimeMinValue = value;
}
}
}
/// <summary>
/// the current maximum value.
/// 当前最大值。
/// </summary>
public float runtimeMaxValue { get; internal set; }
public float runtimeMaxValue
{
get { return m_RuntimeMaxValue; }
internal set
{
if (value != m_RuntimeMaxValue)
{
if (m_RuntimeMaxValueFirstChanged)
{
m_RuntimeMaxValueFirstChanged = false;
}
else
{
m_RuntimeLastMaxValue = m_RuntimeMaxValue;
m_RuntimeMaxValueChanged = true;
m_RuntimeMaxValueUpdateTime = Time.time;
}
m_RuntimeMaxValue = value;
}
}
}
/// <summary>
/// the x offset of zero position.
/// 坐标轴原点在X轴的偏移。
@@ -232,6 +272,16 @@ namespace XCharts
private GameObject m_TooltipLabel;
private Text m_TooltipLabelText;
private RectTransform m_TooltipLabelRect;
private float m_RuntimeMinValue;
private float m_RuntimeLastMinValue;
private bool m_RuntimeMinValueChanged;
private float m_RuntimeMinValueUpdateTime;
private float m_RuntimeMaxValue;
private float m_RuntimeLastMaxValue;
private bool m_RuntimeMaxValueChanged;
private float m_RuntimeMaxValueUpdateTime;
private bool m_RuntimeMinValueFirstChanged = true;
private bool m_RuntimeMaxValueFirstChanged = true;
public void Copy(Axis other)
{
@@ -528,13 +578,15 @@ namespace XCharts
/// 更新刻度标签文字
/// </summary>
/// <param name="dataZoom"></param>
internal void UpdateLabelText(float coordinateWidth, DataZoom dataZoom, bool forcePercent)
internal void UpdateLabelText(float coordinateWidth, DataZoom dataZoom, bool forcePercent, float duration)
{
var minValue = GetCurrMinValue(duration);
var maxValue = GetCurrMaxValue(duration);
for (int i = 0; i < axisLabelTextList.Count; i++)
{
if (axisLabelTextList[i] != null)
{
axisLabelTextList[i].text = GetLabelName(coordinateWidth, i, runtimeMinValue, runtimeMaxValue, dataZoom, forcePercent);
axisLabelTextList[i].text = GetLabelName(coordinateWidth, i, minValue, maxValue, dataZoom, forcePercent);
}
}
}
@@ -591,7 +643,7 @@ namespace XCharts
/// </summary>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
internal void AdjustMinMaxValue(ref float minValue, ref float maxValue)
internal void AdjustMinMaxValue(ref float minValue, ref float maxValue, bool needFormat)
{
if (minMaxType == Axis.AxisMinMaxType.Custom)
{
@@ -609,28 +661,74 @@ namespace XCharts
if (minValue > 0 && maxValue > 0)
{
minValue = 0;
maxValue = ChartHelper.GetMaxDivisibleValue(maxValue);
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue) : maxValue;
}
else if (minValue < 0 && maxValue < 0)
{
minValue = ChartHelper.GetMinDivisibleValue(minValue);
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue) : minValue;
maxValue = 0;
}
else
{
minValue = ChartHelper.GetMinDivisibleValue(minValue);
maxValue = ChartHelper.GetMaxDivisibleValue(maxValue);
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue) : minValue;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue) : maxValue;
}
break;
case Axis.AxisMinMaxType.MinMax:
minValue = ChartHelper.GetMinDivisibleValue(minValue);
maxValue = ChartHelper.GetMaxDivisibleValue(maxValue);
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue) : minValue;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue) : maxValue;
break;
}
}
m_ValueRange = maxValue - minValue;
}
internal float GetCurrMinValue(float duration)
{
if (!m_RuntimeMinValueChanged) return m_RuntimeMinValue;
var time = Time.time - m_RuntimeMinValueUpdateTime;
var total = duration / 1000;
if (duration > 0 && time <= total)
{
var curr = Mathf.Lerp(m_RuntimeLastMinValue, m_RuntimeMinValue, time / total);
return curr;
}
else
{
m_RuntimeMinValueChanged = false;
return m_RuntimeMinValue;
}
}
internal float GetCurrMaxValue(float duration)
{
if (!m_RuntimeMaxValueChanged) return m_RuntimeMaxValue;
var time = Time.time - m_RuntimeMaxValueUpdateTime;
var total = duration / 1000;
if (duration > 0 && time <= total)
{
var curr = Mathf.Lerp(m_RuntimeLastMaxValue, m_RuntimeMaxValue, time / total);
return curr;
}
else
{
m_RuntimeMaxValueChanged = false;
return m_RuntimeMaxValue;
}
}
public bool IsValueChanging(float duration)
{
if (GetCurrMinValue(duration) != m_RuntimeMinValue || GetCurrMaxValue(duration) != m_RuntimeMaxValue)
{
return true;
}
else
{
return false;
}
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))

View File

@@ -48,6 +48,10 @@ namespace XCharts
/// 热力图。主要通过颜色去表现数值的大小,必须要配合 visualMap 组件使用。
/// </summary>
Heatmap,
/// <summary>
/// 仪表盘。
/// </summary>
Gauge,
}
/// <summary>
@@ -142,6 +146,21 @@ namespace XCharts
Capsule
}
/// <summary>
/// 仪表盘类型
/// </summary>
public enum GaugeType
{
/// <summary>
/// 指针型
/// </summary>
Pointer,
/// <summary>
/// 进度条型
/// </summary>
ProgressBar
}
/// <summary>
/// 采样类型
/// </summary>
@@ -202,6 +221,16 @@ namespace XCharts
[SerializeField] private float m_BarZebraWidth = 4f;
[SerializeField] private float m_BarZebraGap = 2f;
[SerializeField] private float m_Min;
[SerializeField] private float m_Max;
[SerializeField] private float m_StartAngle;
[SerializeField] private float m_EndAngle;
[SerializeField] private bool m_Clockwise;
[SerializeField] private bool m_ArcShaped;
[SerializeField] private int m_SplitNumber;
[SerializeField] private GaugeType m_GaugeType = GaugeType.Pointer;
[SerializeField] private GaugeAxis m_GaugeAxis = new GaugeAxis();
[SerializeField] private GaugePointer m_GaugePointer = new GaugePointer();
[SerializeField] private bool m_ClickOffset = true;
[SerializeField] private RoseType m_RoseType = RoseType.None;
@@ -213,6 +242,7 @@ namespace XCharts
[SerializeField] private LineArrow m_LineArrow = new LineArrow();
[SerializeField] private ItemStyle m_ItemStyle = new ItemStyle();
[SerializeField] private Emphasis m_Emphasis = new Emphasis();
[SerializeField] private TitleStyle m_TitleStyle = new TitleStyle();
[SerializeField] [Range(1, 10)] private int m_ShowDataDimension;
[SerializeField] private bool m_ShowDataName;
[SerializeField] private bool m_ShowDataIcon;
@@ -383,15 +413,59 @@ namespace XCharts
/// </summary>
public float pieSpace { get { return m_Space; } set { m_Space = value; } }
/// <summary>
/// the center of pie chart.
/// 饼图的中心点。
/// the center of chart.
/// 中心点。
/// </summary>
public float[] pieCenter { get { return m_Center; } set { m_Center = value; } }
public float[] center { get { return m_Center; } set { m_Center = value; } }
/// <summary>
/// the radius of pie chart.
/// 饼图的半径。radius[0]表示内径radius[1]表示外径。
/// the radius of chart.
/// 半径。radius[0]表示内径radius[1]表示外径。
/// </summary>
public float[] pieRadius { get { return m_Radius; } set { m_Radius = value; } }
public float[] radius { get { return m_Radius; } set { m_Radius = value; } }
[Obsolete("Use Serie.center instead.", true)]
public float[] pieCenter { get { return center; } set { center = value; } }
[Obsolete("Use Serie.radius instead.", true)]
public float[] pieRadius { get { return radius; } set { radius = value; } }
/// <summary>
/// 最小值,映射到 startAngle。
/// </summary>
public float min { get { return m_Min; } set { m_Min = value; } }
/// <summary>
/// 最大值,映射到 endAngle。
/// </summary>
public float max { get { return m_Max; } set { m_Max = value; } }
/// <summary>
/// 起始角度。和时钟一样12点钟位置是0度顺时针到360度。
/// </summary>
public float startAngle { get { return m_StartAngle; } set { m_StartAngle = value; } }
/// <summary>
/// 结束角度。和时钟一样12点钟位置是0度顺时针到360度。
/// </summary>
public float endAngle { get { return m_EndAngle; } set { m_EndAngle = value; } }
/// <summary>
/// 是否顺时针。
/// </summary>
public bool clockwise { get { return m_Clockwise; } set { m_Clockwise = value; } }
/// <summary>
/// 刻度分割段数。
/// </summary>
public int splitNumber { get { return m_SplitNumber; } set { m_SplitNumber = value > 36 ? 36 : value; } }
/// <summary>
/// 是否开启圆弧形边角。
/// </summary>
public bool arcShaped { get { return m_ArcShaped; } set { m_ArcShaped = value; } }
/// <summary>
/// 仪表盘轴线。
/// </summary>
public GaugeAxis gaugeAxis { get { return m_GaugeAxis; } set { m_GaugeAxis = value; } }
/// <summary>
/// 仪表盘指针。
/// </summary>
public GaugePointer gaugePointer { get { return m_GaugePointer; } set { m_GaugePointer = value; } }
/// <summary>
/// 仪表盘类型。
/// </summary>
public GaugeType gaugeType { get { return m_GaugeType; } set { m_GaugeType = value; } }
/// <summary>
/// Text label of graphic element,to explain some data information about graphic item like value, name and so on.
/// 图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。
@@ -416,6 +490,10 @@ namespace XCharts
/// 高亮的图形样式和文本标签样式。
/// </summary>
public Emphasis emphasis { get { return m_Emphasis; } set { m_Emphasis = value; } }
/// <summary>
/// 标题样式。
/// </summary>
public TitleStyle titleStyle { get { return m_TitleStyle; } set { m_TitleStyle = value; } }
/// <summary>
/// 系列中的数据内容数组。SerieData可以设置1到n维数据。
@@ -444,15 +522,15 @@ namespace XCharts
/// <summary>
/// 饼图的中心点位置。
/// </summary>
public Vector3 runtimePieCenterPos { get; internal set; }
public Vector3 runtimeCenterPos { get; internal set; }
/// <summary>
/// 饼图的内径
/// </summary>
public float runtimePieInsideRadius { get; internal set; }
public float runtimeInsideRadius { get; internal set; }
/// <summary>
/// 饼图的外径
/// </summary>
public float runtimePieOutsideRadius { get; internal set; }
public float runtimeOutsideRadius { get; internal set; }
/// <summary>
/// 饼图的数据项最大值
/// </summary>
@@ -732,6 +810,17 @@ namespace XCharts
return 0;
}
public float GetYCurrData(int index, DataZoom dataZoom = null)
{
if (index < 0) return 0;
var serieData = GetDataList(dataZoom);
if (index < serieData.Count)
{
return serieData[index].GetCurrData(1, animation.GetUpdateAnimationDuration());
}
return 0;
}
/// <summary>
/// 获得维度Y索引对应的数据和数据名
/// </summary>
@@ -768,6 +857,24 @@ namespace XCharts
return null;
}
/// <summary>
/// 获得指定索引的数据项的Label
/// </summary>
/// <param name="index"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
public SerieLabel GetSerieLabel(int index, DataZoom dataZoom = null)
{
var data = GetDataList(dataZoom);
if (index >= 0 && index <= data.Count - 1)
{
var serieData = data[index];
if (serieData.enableLabel) return serieData.label;
else return label;
}
return null;
}
/// <summary>
/// 获得指定索引的维度X和维度Y的数据
/// </summary>
@@ -896,9 +1003,9 @@ namespace XCharts
public void UpdateData(int index, int dimension, float value)
{
if (index < 0) return;
if (index < m_Data.Count && dimension < m_Data[index].data.Count)
if (index < m_Data.Count)
{
m_Data[index].data[dimension] = value;
m_Data[index].UpdateData(dimension, value);
}
}
@@ -1083,6 +1190,22 @@ namespace XCharts
return false;
}
/// <summary>
/// 更新运行时中心点和半径
/// </summary>
/// <param name="chartWidth"></param>
/// <param name="chartHeight"></param>
internal void UpdateCenter(float chartWidth, float chartHeight)
{
if (center.Length < 2) return;
var centerX = center[0] <= 1 ? chartWidth * center[0] : center[0];
var centerY = center[1] <= 1 ? chartHeight * center[1] : center[1];
runtimeCenterPos = new Vector2(centerX, centerY);
var minWidth = Mathf.Min(chartWidth, chartHeight);
runtimeInsideRadius = radius[0] <= 1 ? minWidth * radius[0] : radius[0];
runtimeOutsideRadius = radius[1] <= 1 ? minWidth * radius[1] : radius[1];
}
/// <summary>
/// 设置指定index的数据图标的尺寸
/// </summary>

View File

@@ -81,6 +81,18 @@ namespace XCharts
}
}
public float GetCurrData(int serieIndex, int dataIndex)
{
if (serieIndex >= 0 && serieIndex < Count)
{
return m_Series[serieIndex].GetYCurrData(dataIndex);
}
else
{
return 0;
}
}
/// <summary>
/// 获得指定系列名的第一个系列
/// </summary>
@@ -167,6 +179,18 @@ namespace XCharts
return false;
}
internal bool IsAnyUpdateAnimationSerie()
{
foreach (var serie in m_Series)
{
if (serie.animation.enable && serie.animation.updateAnimation)
{
return true;
}
}
return false;
}
/// <summary>
/// 获得上一个同堆叠且显示的serie。
/// </summary>
@@ -603,8 +627,9 @@ namespace XCharts
{
if (yValue)
{
if (data.data[1] > max) max = data.data[1];
if (data.data[1] < min) min = data.data[1];
var currData = data.GetData(1);
if (currData > max) max = currData;
if (currData < min) min = currData;
}
else
{
@@ -641,7 +666,7 @@ namespace XCharts
if (!_serieTotalValueForMinMax.ContainsKey(j))
_serieTotalValueForMinMax[j] = 0;
_serieTotalValueForMinMax[j] = _serieTotalValueForMinMax[j] +
(yValue ? showData[j].data[1] : showData[i].data[0]);
(yValue ? showData[j].GetData(1) : showData[i].data[0]);
}
}
@@ -668,7 +693,9 @@ namespace XCharts
{
minVaule = Mathf.FloorToInt(min);
maxValue = Mathf.CeilToInt(max);
}else{
}
else
{
minVaule = min;
maxValue = max;
}

View File

@@ -0,0 +1,305 @@
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
/// <summary>
/// Settings related to gauge axis line.
/// 仪表盘轴线相关设置。
/// </summary>
[System.Serializable]
public class GaugeAxis : SubComponent
{
[System.Serializable]
public class AxisLine
{
[System.Serializable]
public class StageColor
{
[SerializeField] private float m_Percent;
[SerializeField] private Color m_Color;
/// <summary>
/// 结束位置百分比。
/// </summary>
public float percent { get { return m_Percent; } set { m_Percent = value; } }
/// <summary>
/// 颜色。
/// </summary>
public Color color { get { return m_Color; } set { m_Color = value; } }
public StageColor(float percent, Color color)
{
m_Percent = percent;
m_Color = color;
}
}
[SerializeField] private bool m_Show = true;
[SerializeField] private float m_Width = 15f;
[SerializeField] private float m_Opacity = 1f;
[SerializeField] private Color m_BarColor;
[SerializeField] private Color m_BarBackgroundColor = new Color32(200, 200, 200, 255);
[SerializeField]
private List<StageColor> m_StageColor = new List<StageColor>()
{
new StageColor(0.2f,new Color32(145,199,174,255)),
new StageColor(0.8f,new Color32(99,134,158,255)),
new StageColor(1.0f,new Color32(194,53,49,255)),
};
/// <summary>
/// Set this to false to prevent the axis line from showing.
/// 是否显示坐标轴轴线。
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// line style line width.
/// 坐标轴线线宽。
/// </summary>
public float width { get { return m_Width; } set { m_Width = value; } }
/// <summary>
/// The opacity of axis line.
/// 透明度。
/// </summary>
public float opacity { get { return m_Opacity; } set { m_Opacity = value; } }
/// <summary>
/// 进度条颜色。
/// </summary>
public Color barColor { get { return m_BarColor; } set { m_BarColor = value; } }
/// <summary>
/// 进度条背景颜色。
/// </summary>
public Color barBackgroundColor { get { return m_BarBackgroundColor; } set { m_BarBackgroundColor = value; } }
/// <summary>
/// 阶段颜色。
/// </summary>
public List<StageColor> stageColor { get { return m_StageColor; } set { m_StageColor = value; } }
}
/// <summary>
/// 分割线
/// </summary>
[System.Serializable]
public class SplitLine
{
[SerializeField] private bool m_Show = true;
[SerializeField] private float m_Length = 15;
[SerializeField]
private LineStyle m_LineStyle = new LineStyle()
{
width = 1.5f,
type = LineStyle.Type.Solid,
color = new Color32(238, 238, 238, 255)
};
/// <summary>
/// 是否显示分割线。
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// 分割线长度。
/// </summary>
public float length { get { return m_Length; } set { m_Length = value; } }
/// <summary>
/// 分割线样式。
/// </summary>
public LineStyle lineStyle { get { return m_LineStyle; } set { m_LineStyle = value; } }
}
/// <summary>
/// 刻度
/// </summary>
[System.Serializable]
public class AxisTick
{
[SerializeField] private bool m_Show = true;
[SerializeField] private float m_Length = 5;
[SerializeField] private float m_SplitNumber = 5;
[SerializeField]
private LineStyle m_LineStyle = new LineStyle()
{
width = 1f,
type = LineStyle.Type.Solid,
color = new Color32(238, 238, 238, 255)
};
/// <summary>
/// 是否显示刻度。
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// 刻度长度。当为0-1的浮点数时表示半径的百分比。
/// </summary>
public float length { get { return m_Length; } set { m_Length = value; } }
/// <summary>
/// 分割线之间的分割段数。
/// </summary>
public float splitNumber { get { return m_SplitNumber; } set { m_SplitNumber = value; } }
/// <summary>
/// 刻度线样式。
/// </summary>
public LineStyle lineStyle { get { return m_LineStyle; } set { m_LineStyle = value; } }
}
[SerializeField] private bool m_Show = true;
[SerializeField] private AxisLine m_AxisLine = new AxisLine();
[SerializeField] private SplitLine m_SplitLine = new SplitLine();
[SerializeField] private AxisTick m_AxisTick = new AxisTick();
[SerializeField] private SerieLabel m_AxisLabel = new SerieLabel();
[SerializeField] private List<string> m_AxisLabelText = new List<string>();
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// 仪表盘轴线。
/// </summary>
public AxisLine axisLine { get { return m_AxisLine; } set { m_AxisLine = value; } }
/// <summary>
/// 分割线。
/// </summary>
public SplitLine splitLine { get { return m_SplitLine; } set { m_SplitLine = value; } }
/// <summary>
/// 刻度。
/// </summary>
public AxisTick axisTick { get { return m_AxisTick; } set { m_AxisTick = value; } }
/// <summary>
/// 文本标签。
/// </summary>
public SerieLabel axisLabel { get { return m_AxisLabel; } set { m_AxisLabel = value; } }
/// <summary>
/// 自定义Label的内容。
/// </summary>
public List<string> axisLabelText { get { return m_AxisLabelText; } set { m_AxisLabelText = value; } }
public List<float> runtimeStageAngle = new List<float>();
public List<Vector3> runtimeLabelPosition = new List<Vector3>();
private List<LabelObject> m_RuntimeLabelList = new List<LabelObject>();
internal Color GetAxisLineColor(ThemeInfo theme, int index)
{
var color = axisLine.barColor != Color.clear ? axisLine.barColor : (Color)theme.GetColor(index);
color.a *= axisLine.opacity;
return color;
}
internal Color GetAxisLineBackgroundColor(ThemeInfo theme, int index)
{
var color = axisLine.barBackgroundColor != Color.clear ? axisLine.barBackgroundColor : Color.grey;
color.a *= axisLine.opacity;
return color;
}
internal Color GetSplitLineColor(ThemeInfo theme, int serieIndex, float angle)
{
Color color;
if (splitLine.lineStyle.color != Color.clear)
{
color = splitLine.lineStyle.color;
color.a *= splitLine.lineStyle.opacity;
return color;
}
for (int i = 0; i < runtimeStageAngle.Count; i++)
{
if (angle < runtimeStageAngle[i])
{
color = axisLine.stageColor[i].color;
color.a *= splitLine.lineStyle.opacity;
return color;
}
}
color = theme.GetColor(serieIndex);
color.a *= splitLine.lineStyle.opacity;
return color;
}
internal Color GetAxisTickColor(ThemeInfo theme, int serieIndex, float angle)
{
Color color;
if (axisTick.lineStyle.color != Color.clear)
{
color = axisTick.lineStyle.color;
color.a *= axisTick.lineStyle.opacity;
return color;
}
for (int i = 0; i < runtimeStageAngle.Count; i++)
{
if (angle < runtimeStageAngle[i])
{
color = axisLine.stageColor[i].color;
color.a *= axisTick.lineStyle.opacity;
return color;
}
}
color = theme.GetColor(serieIndex);
color.a *= axisTick.lineStyle.opacity;
return color;
}
internal Color GetPointerColor(ThemeInfo theme, int serieIndex, float angle, ItemStyle itemStyle)
{
Color color;
if (itemStyle.color != Color.clear)
{
color = itemStyle.color;
color.a *= itemStyle.opacity;
return color;
}
for (int i = 0; i < runtimeStageAngle.Count; i++)
{
if (angle < runtimeStageAngle[i])
{
color = axisLine.stageColor[i].color;
color.a *= itemStyle.opacity;
return color;
}
}
color = theme.GetColor(serieIndex);
color.a *= itemStyle.opacity;
return color;
}
public void ClearLabelObject()
{
m_RuntimeLabelList.Clear();
}
public void AddLabelObject(LabelObject label)
{
m_RuntimeLabelList.Add(label);
}
public LabelObject GetLabelObject(int index)
{
if (index >= 0 && index < m_RuntimeLabelList.Count)
{
return m_RuntimeLabelList[index];
}
return null;
}
public void SetLabelObjectPosition(int index, Vector3 pos)
{
if (index >= 0 && index < m_RuntimeLabelList.Count)
{
m_RuntimeLabelList[index].SetPosition(pos);
}
}
public void SetLabelObjectText(int index, string text)
{
if (index >= 0 && index < m_RuntimeLabelList.Count)
{
m_RuntimeLabelList[index].SetText(text);
}
}
public void SetLabelObjectActive(bool flag)
{
foreach (var label in m_RuntimeLabelList)
{
label.SetActive(flag);
}
}
}
}

View File

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

View File

@@ -0,0 +1,40 @@
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
/// <summary>
/// Settings related to gauge pointer.
/// 仪表盘指针相关设置。
/// </summary>
[System.Serializable]
public class GaugePointer : SubComponent
{
[SerializeField] private bool m_Show = true;
[SerializeField] private float m_Length = 0.8f;
[SerializeField] private float m_Width = 15;
/// <summary>
/// 是否显示指针。
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// 指针长度。可以是绝对值也可以是相对于半径的百分比0-1的浮点数
/// </summary>
/// <value></value>
public float length { get { return m_Length; } set { m_Length = value; } }
/// <summary>
/// 指针宽度。
/// </summary>
/// <value></value>
public float width { get { return m_Width; } set { m_Width = value; } }
}
}

View File

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

View File

@@ -23,10 +23,12 @@ namespace XCharts
}
[SerializeField] private bool m_Enable = true;
[SerializeField] private Easing m_Easting;
[SerializeField] private int m_Duration = 1000;
[SerializeField] private float m_Duration = 1000;
[SerializeField] private int m_Threshold = 2000;
[SerializeField] private int m_Delay = 0;
[SerializeField] private int m_ActualDuration;
[SerializeField] private float m_Delay = 0;
[SerializeField] private bool m_UpdateAnimation = false;
[SerializeField] private float m_UpdateDuration = 500;
[SerializeField] private float m_ActualDuration;
/// <summary>
/// Whether to enable animation.
@@ -42,12 +44,12 @@ namespace XCharts
/// The milliseconds duration of the first animation.
/// 设定的动画时长(毫秒)。
/// </summary>
public int duration { get { return m_Duration; } set { m_Duration = value; } }
public float duration { get { return m_Duration; } set { m_Duration = value < 0 ? 0 : value; } }
/// <summary>
/// The milliseconds actual duration of the first animation.
/// 实际的动画时长(毫秒)。
/// </summary>
public int actualDuration { get { return m_ActualDuration; } }
public float actualDuration { get { return m_ActualDuration; } }
/// <summary>
/// Whether to set graphic number threshold to animation. Animation will be disabled when graphic number is larger than threshold.
/// 是否开启动画的阈值,当单个系列显示的图形数量大于这个阈值时会关闭动画。
@@ -57,7 +59,16 @@ namespace XCharts
/// The milliseconds delay before updating the first animation.
/// 动画延时(毫秒)。
/// </summary>
public int delay { get { return m_Delay; } set { m_Delay = value; if (m_Delay < 0) m_Delay = 0; } }
public float delay { get { return m_Delay; } set { m_Delay = value < 0 ? 0 : value; } }
/// <summary>
/// 是否开启数据变更动画。
/// </summary>
public bool updateAnimation { get { return m_UpdateAnimation; } set { m_UpdateAnimation = value; } }
/// <summary>
/// The milliseconds duration of the first animation.
/// 数据变更的动画时长(毫秒)。
/// </summary>
public float updateDuration { get { return m_UpdateDuration; } set { m_UpdateDuration = value < 0 ? 0 : value; } }
private Dictionary<int, float> m_DataAnimationState = new Dictionary<int, float>();
private bool m_IsStart = false;
@@ -232,5 +243,11 @@ namespace XCharts
{
return m_CurrDataProgress;
}
public float GetUpdateAnimationDuration()
{
if (m_Enable && m_UpdateAnimation && IsFinish()) return m_UpdateDuration;
else return 0;
}
}
}

View File

@@ -24,6 +24,8 @@ namespace XCharts
[SerializeField] private bool m_Selected;
[SerializeField] private float m_Radius;
[SerializeField] private IconStyle m_IconStyle = new IconStyle();
[SerializeField] private bool m_EnableLabel = false;
[SerializeField] private SerieLabel m_Label = new SerieLabel();
[SerializeField] private List<float> m_Data = new List<float>();
private bool m_Show = true;
@@ -58,6 +60,14 @@ namespace XCharts
/// </summary>
public IconStyle iconStyle { get { return m_IconStyle; } set { m_IconStyle = value; } }
/// <summary>
/// 是否启用单个数据项的标签设置。
/// </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>
/// An arbitrary dimension data list of data item.
/// 可指定任意维数的数值列表。
/// </summary>
@@ -143,12 +153,67 @@ namespace XCharts
public float runtimePieOffsetRadius { get; internal set; }
public Vector3 runtiemPieOffsetCenter { get; internal set; }
private bool m_DataChanged;
private float m_LastData;
private float m_DataUpdateTime;
public float GetData(int index)
{
if (index >= 0 && index < m_Data.Count) return m_Data[index];
if (index >= 0 && index < m_Data.Count)
{
return m_Data[index];
}
else return 0;
}
public float GetCurrData(int index, float animationDuration = 500f)
{
if (index == 1 && m_DataChanged)
{
var time = Time.time - m_DataUpdateTime;
var total = animationDuration / 1000;
if (animationDuration > 0 && time <= total)
{
var curr = Mathf.Lerp(m_LastData, GetData(index), time / total);
return curr;
}
else
{
m_DataChanged = false;
return GetData(index);
}
}
else
{
return GetData(index);
}
}
public float GetLastData(int index)
{
if (index == 1 && m_DataChanged) return m_LastData;
else return GetData(index);
}
public void UpdateData(int dimension, float value)
{
if (dimension >= 0 && dimension < data.Count)
{
if (dimension == 1)
{
m_LastData = data[dimension];
m_DataUpdateTime = Time.time;
m_DataChanged = true;
}
data[dimension] = value;
}
}
public bool IsDataChanged()
{
return m_DataChanged;
}
public void InitLabel(GameObject labelObj, bool autoSize, float paddingLeftRight, float paddingTopBottom)
{
gameObject = labelObj;
@@ -169,7 +234,7 @@ namespace XCharts
public bool SetLabelText(string text)
{
if (labelText)
if (labelText && !labelText.text.Equals(text))
{
labelText.text = text;
if (m_LabelAutoSize)
@@ -185,6 +250,14 @@ namespace XCharts
return false;
}
public void SetLabelColor(Color color)
{
if (labelText)
{
labelText.color = color;
}
}
public float GetLabelWidth()
{
if (labelRect) return labelRect.sizeDelta.x;
@@ -224,5 +297,16 @@ namespace XCharts
if (iconStyle == null) return;
iconStyle.UpdateIcon();
}
public bool IsInitLabel()
{
return labelText != null;
}
public SerieLabel GetSerieLabel(SerieLabel parentLabel)
{
if (enableLabel) return label;
else return parentLabel;
}
}
}

View File

@@ -80,6 +80,7 @@ namespace XCharts
[SerializeField] private bool m_Show = false;
[SerializeField] Position m_Position;
[SerializeField] private Vector3 m_Offset;
[SerializeField] private float m_Margin;
[SerializeField] private string m_Formatter;
[SerializeField] private float m_Rotate = 0;
[SerializeField] private float m_PaddingLeftRight = 2f;
@@ -130,6 +131,10 @@ namespace XCharts
/// </summary>
public Vector3 offset { get { return m_Offset; } set { m_Offset = value; } }
/// <summary>
/// 距离轴线的距离。
/// </summary>
public float margin { get { return m_Margin; } set { m_Margin = value; } }
/// <summary>
/// Text color,If set as default ,the color will assigned as series color.
/// 自定义文字颜色,默认和系列的颜色一致。
/// </summary>

View File

@@ -0,0 +1,109 @@
/*
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using System;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
/// <summary>
/// the title of serie.
/// 标题相关设置。
/// </summary>
[Serializable]
public class TitleStyle : SubComponent, IEquatable<TitleStyle>
{
[SerializeField] private bool m_Show;
[SerializeField] private TextStyle m_textStyle = new TextStyle(18);
/// <summary>
/// Whether to show title.
/// 是否显示标题。
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
/// <summary>
/// the color of text.
/// 文本的颜色。
/// </summary>
public TextStyle textStyle { get { return m_textStyle; } set { m_textStyle = value; } }
/// <summary>
///
/// </summary>
public Text runtimeText { get; set; }
public TitleStyle Clone()
{
var title = new TitleStyle();
title.show = show;
title.textStyle = textStyle.Clone();
return title;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
else if (obj is TitleStyle)
{
return Equals((TitleStyle)obj);
}
else
{
return false;
}
}
public bool Equals(TitleStyle other)
{
if (ReferenceEquals(null, other))
{
return false;
}
return textStyle.Equals(other.textStyle);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public bool IsInited()
{
return runtimeText != null;
}
public void SetActive(bool active)
{
if (runtimeText)
{
ChartHelper.SetActive(runtimeText, active);
}
}
public void UpdatePosition(Vector3 pos)
{
if (runtimeText)
{
runtimeText.transform.localPosition = pos + new Vector3(m_textStyle.offset.x, m_textStyle.offset.y);
}
}
public void SetText(string text)
{
if (runtimeText)
{
if (textStyle.color != Color.clear) runtimeText.color = textStyle.color;
runtimeText.text = text;
}
}
}
}

View File

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

432
Runtime/GaugeChart.cs Normal file
View File

@@ -0,0 +1,432 @@
using System;
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
[AddComponentMenu("XCharts/GaugeChart", 19)]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
[DisallowMultipleComponent]
public class GaugeChart : BaseChart
{
private static readonly string s_AxisLabelObjectName = "axis_label";
private bool m_UpdateTitleText = false;
private bool m_UpdateLabelText = false;
protected override void Awake()
{
base.Awake();
InitAxisLabel();
}
protected override void Start()
{
base.Start();
foreach (var serie in m_Series.list)
{
UpdateTitle(serie);
UpdateLabel(serie);
}
UpdateTitleAndLabelText();
}
protected override void Update()
{
base.Update();
if (m_UpdateLabelText || m_UpdateTitleText)
{
m_UpdateTitleText = false;
m_UpdateLabelText = false;
UpdateTitleAndLabelText();
}
}
#if UNITY_EDITOR
protected override void Reset()
{
base.Reset();
RemoveData();
m_Title.text = "GuageChart";
var serie = AddSerie(SerieType.Gauge, "serie1");
serie.min = 0;
serie.max = 100;
serie.startAngle = -125;
serie.endAngle = 125;
serie.center[0] = 0.5f;
serie.center[1] = 0.5f;
serie.radius[0] = 80;
serie.splitNumber = 5;
serie.animation.updateAnimation = true;
serie.titleStyle.show = true;
serie.titleStyle.textStyle.offset = new Vector2(0, 20);
serie.label.show = true;
serie.label.offset = new Vector3(0, -30);
serie.itemStyle.show = true;
serie.gaugeAxis.axisLabel.show = true;
serie.gaugeAxis.axisLabel.margin = 18;
AddData(0, UnityEngine.Random.Range(10, 90), "title");
InitAxisLabel();
}
#endif
private void InitAxisLabel()
{
Debug.LogError("InitAxisLabel");
var labelObject = ChartHelper.AddObject(s_AxisLabelObjectName, transform, Vector2.zero,
Vector2.zero, Vector2.zero, new Vector2(chartWidth, chartHeight));
SerieLabelPool.ReleaseAll(labelObject.transform);
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
var serieLabel = serie.gaugeAxis.axisLabel;
serie.gaugeAxis.ClearLabelObject();
var count = serie.splitNumber > 36 ? 36 : (serie.splitNumber + 1);
var startAngle = serie.startAngle;
Debug.LogError("InitAxisLabel:"+serie.name+","+count);
for (int j = 0; j < count; j++)
{
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, i, j);
var color = Color.grey;
var labelObj = SerieLabelPool.Get(textName, labelObject.transform, serieLabel, m_ThemeInfo.font, color, 100, 100);
var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
var item = new LabelObject();
item.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
item.SetIcon(iconImage);
item.SetIconActive(false);
serie.gaugeAxis.AddLabelObject(item);
}
UpdateAxisLabel(serie);
}
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
DrawData(vh);
}
protected override void OnThemeChanged()
{
base.OnThemeChanged();
}
private void DrawData(VertexHelper vh)
{
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if (serie.type != SerieType.Gauge) continue;
DrawGauge(vh, serie);
}
}
private void DrawGauge(VertexHelper vh, Serie serie)
{
serie.UpdateCenter(chartWidth, chartHeight);
var destAngle = GetCurrAngle(serie, true);
serie.animation.InitProgress(0, serie.startAngle, destAngle);
var currAngle = serie.animation.IsFinish() ? GetCurrAngle(serie, false) : serie.animation.GetCurrDetail();
DrawProgressBar(vh, serie, currAngle);
DrawStageColor(vh, serie);
DrawSplitLine(vh, serie);
DrawAxisTick(vh, serie);
DrawPointer(vh, serie, currAngle);
UpdateTitle(serie);
// UpdateAxisLabel(serie);
UpdateLabel(serie);
CheckAnimation(serie);
if (!serie.animation.IsFinish())
{
float duration = serie.animation.duration > 0 ? (float)serie.animation.duration / 1000 : 1;
float speed = (destAngle - serie.startAngle) / duration;
serie.animation.CheckProgress(Time.deltaTime * speed);
RefreshChart();
}
else if (NeedRefresh(serie))
{
RefreshChart();
}
}
private void DrawProgressBar(VertexHelper vh, Serie serie, float currAngle)
{
if (serie.gaugeType != GaugeType.ProgressBar) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisLine.show) return;
var color = serie.gaugeAxis.GetAxisLineColor(m_ThemeInfo, serie.index);
var backgroundColor = serie.gaugeAxis.GetAxisLineBackgroundColor(m_ThemeInfo, serie.index);
var outsideRadius = serie.runtimeInsideRadius + serie.gaugeAxis.axisLine.width;
ChartDrawer.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
backgroundColor, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, serie.startAngle, serie.endAngle);
if (serie.arcShaped)
{
DrawArcShape(vh, serie, serie.startAngle, backgroundColor, true);
DrawArcShape(vh, serie, serie.endAngle, backgroundColor);
}
ChartDrawer.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
color, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, serie.startAngle, currAngle);
if (serie.arcShaped && currAngle != serie.startAngle)
{
DrawArcShape(vh, serie, currAngle, color);
DrawArcShape(vh, serie, serie.startAngle, color, true);
}
}
private void DrawStageColor(VertexHelper vh, Serie serie)
{
if (serie.gaugeType != GaugeType.Pointer) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisLine.show) return;
var totalAngle = serie.endAngle - serie.startAngle;
var tempStartAngle = serie.startAngle;
var tempEndAngle = serie.startAngle;
var outsideRadius = serie.runtimeInsideRadius + serie.gaugeAxis.axisLine.width;
serie.gaugeAxis.runtimeStageAngle.Clear();
for (int i = 0; i < serie.gaugeAxis.axisLine.stageColor.Count; i++)
{
var stageColor = serie.gaugeAxis.axisLine.stageColor[i];
tempEndAngle = serie.startAngle + totalAngle * stageColor.percent;
serie.gaugeAxis.runtimeStageAngle.Add(tempEndAngle);
ChartDrawer.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
stageColor.color, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, tempStartAngle, tempEndAngle);
tempStartAngle = tempEndAngle;
}
}
private void DrawPointer(VertexHelper vh, Serie serie, float currAngle)
{
if (!serie.gaugePointer.show) return;
var pointerColor = serie.gaugeAxis.GetPointerColor(m_ThemeInfo, serie.index, currAngle, serie.itemStyle);
var len = serie.gaugePointer.length < 1 && serie.gaugePointer.length > -1 ?
serie.runtimeInsideRadius * serie.gaugePointer.length :
serie.gaugePointer.length;
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle, len);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 180, serie.gaugePointer.width);
var p3 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle - 90, serie.gaugePointer.width / 2);
var p4 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 90, serie.gaugePointer.width / 2);
ChartDrawer.DrawPolygon(vh, p1, p3, p2, p4, pointerColor);
}
private void DrawSplitLine(VertexHelper vh, Serie serie)
{
if (serie.gaugeType != GaugeType.Pointer) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.splitLine.show) return;
if (serie.splitNumber <= 0) return;
var splitLine = serie.gaugeAxis.splitLine;
var totalAngle = serie.endAngle - serie.startAngle;
var diffAngle = totalAngle / serie.splitNumber;
var outsideRadius = serie.runtimeInsideRadius + serie.gaugeAxis.axisLine.width;
var insideRadius = outsideRadius - splitLine.length;
var lineWidth = splitLine.lineStyle.width;
for (int i = 0; i < serie.splitNumber + 1; i++)
{
var angle = serie.startAngle + i * diffAngle;
var lineColor = serie.gaugeAxis.GetSplitLineColor(m_ThemeInfo, serie.index, angle);
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, insideRadius);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, outsideRadius);
ChartDrawer.DrawLine(vh, p1, p2, lineWidth, lineColor);
}
}
private void DrawAxisTick(VertexHelper vh, Serie serie)
{
if (serie.gaugeType != GaugeType.Pointer) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisTick.show) return;
if (serie.splitNumber <= 0) return;
var axisTick = serie.gaugeAxis.axisTick;
var totalAngle = serie.endAngle - serie.startAngle;
var diffAngle = totalAngle / serie.splitNumber;
var outsideRadius = serie.runtimeInsideRadius + serie.gaugeAxis.axisLine.width;
var insideRadius = outsideRadius - (axisTick.length < 1 ? serie.gaugeAxis.axisLine.width * axisTick.length : axisTick.length);
var lineWidth = axisTick.lineStyle.width;
for (int i = 0; i < serie.splitNumber; i++)
{
for (int j = 1; j < axisTick.splitNumber; j++)
{
var angle = serie.startAngle + i * diffAngle + j * (diffAngle / axisTick.splitNumber);
var lineColor = serie.gaugeAxis.GetSplitLineColor(m_ThemeInfo, serie.index, angle);
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, insideRadius);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, outsideRadius);
ChartDrawer.DrawLine(vh, p1, p2, lineWidth, lineColor);
}
}
}
private bool NeedRefresh(Serie serie)
{
if (serie.type == SerieType.Gauge)
{
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
var destValue = serieData.GetData(1);
var currValue = serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
return destValue != currValue;
}
}
return false;
}
private void DrawArcShape(VertexHelper vh, Serie serie, float angle, Color color, bool invert = false)
{
var radius = serie.gaugeAxis.axisLine.width / 2;
var len = serie.runtimeInsideRadius + radius;
var pos = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, len);
var startAngle = invert ? angle + 180 : angle;
var endAngle = invert ? angle + 360 : angle + 180;
ChartDrawer.DrawSector(vh, pos, radius, color, startAngle, endAngle);
}
private void CheckAnimation(Serie serie)
{
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
var value = serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
var data = serieData.GetData(1);
if (value != data) m_RefreshChart = true;
}
}
private void UpdateTitle(Serie serie)
{
if (serie.titleStyle.show)
{
if (serie.titleStyle.IsInited())
{
serie.titleStyle.SetActive(true);
serie.titleStyle.UpdatePosition(serie.runtimeCenterPos);
m_UpdateTitleText = true;
}
else
{
m_ReinitTitle = true;
}
}
else
{
serie.titleStyle.SetActive(false);
}
}
private void UpdateAxisLabel(Serie serie)
{
var show = serie.gaugeAxis.show && serie.gaugeAxis.axisLabel.show;
serie.gaugeAxis.SetLabelObjectActive(show);
if (!show)
{
return;
}
var count = serie.splitNumber > 36 ? 36 : serie.splitNumber;
var startAngle = serie.startAngle;
var totalAngle = serie.endAngle - serie.startAngle;
var totalValue = serie.max - serie.min;
var diffAngle = totalAngle / count;
var diffValue = totalValue / count;
var radius = serie.runtimeInsideRadius - serie.gaugeAxis.axisLabel.margin;
var serieData = serie.GetSerieData(0);
var dataName = serieData != null ? serieData.name : null;
var customLabelText = serie.gaugeAxis.axisLabelText;
for (int j = 0; j <= count; j++)
{
var angle = serie.startAngle + j * diffAngle;
var value = serie.min + j * diffValue;
var pos = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, radius);
var text = customLabelText != null && j < customLabelText.Count ? customLabelText[j] :
serie.gaugeAxis.axisLabel.GetFormatterContent(serie.name, dataName, value, totalValue);
serie.gaugeAxis.SetLabelObjectText(j, text);
serie.gaugeAxis.SetLabelObjectPosition(j, pos);
}
}
private void UpdateLabel(Serie serie)
{
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
if (serie.label.show)
{
if (serieData.IsInitLabel())
{
serieData.SetLabelActive(true);
serieData.SetLabelPosition(serie.runtimeCenterPos + serie.label.offset);
m_UpdateLabelText = true;
}
else
{
m_ReinitLabel = true;
}
}
else
{
serieData.SetLabelActive(false);
}
}
}
private void UpdateTitleAndLabelText()
{
foreach (var serie in m_Series.list)
{
if (serie.type == SerieType.Gauge)
{
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
if (serie.label.show && serieData.IsInitLabel())
{
var value = serieData.GetData(1);
var total = serie.max;
var content = serie.label.GetFormatterContent(serie.name, serieData.name, value, total);
serieData.SetLabelText(content);
if (serie.label.color != Color.clear)
{
serieData.SetLabelColor(serie.label.color);
}
}
if (serie.titleStyle.show && serie.titleStyle.IsInited())
{
serie.titleStyle.SetText(serieData.name);
}
}
UpdateAxisLabel(serie);
}
}
}
private float GetCurrAngle(Serie serie, bool dest)
{
float rangeValue = serie.max - serie.min;
float rangeAngle = serie.endAngle - serie.startAngle;
float value = 0;
float angle = serie.startAngle;
if (serie.dataCount > 0)
{
var serieData = serie.data[0];
value = dest ? serieData.GetData(1) : serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
value = Mathf.Clamp(value, serie.min, serie.max);
}
if (rangeValue > 0)
{
angle += rangeAngle * value / rangeValue;
}
return angle;
}
protected override void OnRefreshLabel()
{
//TODO:
}
}
}

View File

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

View File

@@ -34,9 +34,10 @@ namespace XCharts
IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler,
IDragHandler, IEndDragHandler, IScrollHandler
{
private static readonly string s_TitleObjectName = "title";
private static readonly string s_LegendObjectName = "legend";
private static readonly string s_SerieLabelObjectName = "label";
protected static readonly string s_TitleObjectName = "title";
protected static readonly string s_LegendObjectName = "legend";
protected static readonly string s_SerieLabelObjectName = "label";
protected static readonly string s_SerieTitleObjectName = "serie";
[SerializeField] protected float m_ChartWidth;
[SerializeField] protected float m_ChartHeight;
@@ -62,7 +63,9 @@ namespace XCharts
[NonSerialized] protected bool m_RefreshChart = false;
[NonSerialized] protected bool m_RefreshLabel = false;
[NonSerialized] protected bool m_ReinitLabel = false;
[NonSerialized] protected bool m_ReinitTitle = false;
[NonSerialized] protected bool m_CheckAnimation = false;
[NonSerialized] protected bool m_IsPlayingStartAnimation = false;
[NonSerialized] protected List<string> m_LegendRealShowName = new List<string>();
protected Vector2 chartAnchorMax { get { return rectTransform.anchorMax; } }
@@ -87,6 +90,7 @@ namespace XCharts
InitTitle();
InitLegend();
InitSerieLabel();
InitSerieTitle();
InitTooltip();
m_Series.AnimationStop();
m_Series.AnimationStart();
@@ -300,33 +304,64 @@ namespace XCharts
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
if (!serie.label.show && j > 100) continue;
var serieLabel = serieData.GetSerieLabel(serie.label);
if (!serieLabel.show && j > 100) continue;
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, i, j);
var color = Color.grey;
if (serie.type == SerieType.Pie)
{
color = (serie.label.position == SerieLabel.Position.Inside) ? Color.white :
color = (serieLabel.position == SerieLabel.Position.Inside) ? Color.white :
(Color)m_ThemeInfo.GetColor(count);
}
else
{
color = serie.label.color != Color.clear ? serie.label.color :
color = serieLabel.color != Color.clear ? serieLabel.color :
(Color)m_ThemeInfo.GetColor(i);
}
var labelObj = SerieLabelPool.Get(textName, labelObject.transform, serie.label, m_ThemeInfo.font, color, serieData);
var labelObj = SerieLabelPool.Get(textName, labelObject.transform, serieLabel, m_ThemeInfo.font, color,
serieData.iconStyle.width, serieData.iconStyle.height);
var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
serieData.SetIconImage(iconImage);
var isAutoSize = serie.label.backgroundWidth == 0 || serie.label.backgroundHeight == 0;
serieData.InitLabel(labelObj, isAutoSize, serie.label.paddingLeftRight, serie.label.paddingTopBottom);
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
serieData.InitLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
serieData.SetLabelActive(false);
serieData.SetLabelText(serieData.name);
//serieData.SetLabelText(serieData.name);
count++;
}
}
}
private void InitSerieTitle()
{
var titleObject = ChartHelper.AddObject(s_SerieTitleObjectName, transform, Vector2.zero,
Vector2.zero, Vector2.zero, new Vector2(chartWidth, chartHeight));
ChartHelper.HideAllObject(titleObject);
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
var textStyle = serie.titleStyle.textStyle;
var color = textStyle.color == Color.clear ? m_ThemeInfo.GetColor(i) : (Color32)textStyle.color;
var anchorMin = new Vector2(0.5f, 0.5f);
var anchorMax = new Vector2(0.5f, 0.5f);
var pivot = new Vector2(0.5f, 0.5f);
var fontSize = 10;
var sizeDelta = new Vector2(50, fontSize + 2);
var txt = ChartHelper.AddTextObject("title_" + i, titleObject.transform, m_ThemeInfo.font, color, TextAnchor.MiddleCenter,
anchorMin, anchorMax, pivot, sizeDelta, textStyle.fontSize, textStyle.rotate, textStyle.fontStyle);
txt.text = "";
txt.transform.localPosition = new Vector2(0, 0);
txt.transform.localEulerAngles = Vector2.zero;
ChartHelper.SetActive(txt, false);
serie.titleStyle.runtimeText = txt;
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
txt.text = serieData.name;
}
}
}
private void InitTooltip()
{
@@ -507,6 +542,11 @@ namespace XCharts
m_LegendRealShowName = m_Series.GetSerieNameList();
InitSerieLabel();
}
if (m_ReinitTitle)
{
m_ReinitTitle = false;
InitSerieTitle();
}
if (m_RefreshLabel)
{
m_RefreshLabel = false;
@@ -717,25 +757,26 @@ namespace XCharts
{
var labelHalfWid = serieData.GetLabelWidth() / 2;
var labelHalfHig = serieData.GetLabelHeight() / 2;
var centerPos = serieData.labelPosition + serie.label.offset;
var serieLabel = serieData.GetSerieLabel(serie.label);
var centerPos = serieData.labelPosition + serieLabel.offset;
var p1 = new Vector3(centerPos.x - labelHalfWid, centerPos.y + labelHalfHig);
var p2 = new Vector3(centerPos.x + labelHalfWid, centerPos.y + labelHalfHig);
var p3 = new Vector3(centerPos.x + labelHalfWid, centerPos.y - labelHalfHig);
var p4 = new Vector3(centerPos.x - labelHalfWid, centerPos.y - labelHalfHig);
if (serie.label.rotate > 0)
if (serieLabel.rotate > 0)
{
p1 = ChartHelper.RotateRound(p1, centerPos, Vector3.forward, serie.label.rotate);
p2 = ChartHelper.RotateRound(p2, centerPos, Vector3.forward, serie.label.rotate);
p3 = ChartHelper.RotateRound(p3, centerPos, Vector3.forward, serie.label.rotate);
p4 = ChartHelper.RotateRound(p4, centerPos, Vector3.forward, serie.label.rotate);
p1 = ChartHelper.RotateRound(p1, centerPos, Vector3.forward, serieLabel.rotate);
p2 = ChartHelper.RotateRound(p2, centerPos, Vector3.forward, serieLabel.rotate);
p3 = ChartHelper.RotateRound(p3, centerPos, Vector3.forward, serieLabel.rotate);
p4 = ChartHelper.RotateRound(p4, centerPos, Vector3.forward, serieLabel.rotate);
}
ChartDrawer.DrawPolygon(vh, p1, p2, p3, p4, serie.label.backgroundColor);
ChartDrawer.DrawPolygon(vh, p1, p2, p3, p4, serieLabel.backgroundColor);
if (serie.label.border)
if (serieLabel.border)
{
var borderWid = serie.label.borderWidth;
var borderWid = serieLabel.borderWidth;
p1 = new Vector3(centerPos.x - labelHalfWid, centerPos.y + labelHalfHig + borderWid);
p2 = new Vector3(centerPos.x + labelHalfWid + 2 * borderWid, centerPos.y + labelHalfHig + borderWid);
p3 = new Vector3(centerPos.x + labelHalfWid + borderWid, centerPos.y + labelHalfHig);
@@ -744,21 +785,21 @@ namespace XCharts
var p6 = new Vector3(centerPos.x - labelHalfWid - 2 * borderWid, centerPos.y - labelHalfHig - borderWid);
var p7 = new Vector3(centerPos.x - labelHalfWid - borderWid, centerPos.y - labelHalfHig);
var p8 = new Vector3(centerPos.x - labelHalfWid - borderWid, centerPos.y + labelHalfHig + 2 * borderWid);
if (serie.label.rotate > 0)
if (serieLabel.rotate > 0)
{
p1 = ChartHelper.RotateRound(p1, centerPos, Vector3.forward, serie.label.rotate);
p2 = ChartHelper.RotateRound(p2, centerPos, Vector3.forward, serie.label.rotate);
p3 = ChartHelper.RotateRound(p3, centerPos, Vector3.forward, serie.label.rotate);
p4 = ChartHelper.RotateRound(p4, centerPos, Vector3.forward, serie.label.rotate);
p5 = ChartHelper.RotateRound(p5, centerPos, Vector3.forward, serie.label.rotate);
p6 = ChartHelper.RotateRound(p6, centerPos, Vector3.forward, serie.label.rotate);
p7 = ChartHelper.RotateRound(p7, centerPos, Vector3.forward, serie.label.rotate);
p8 = ChartHelper.RotateRound(p8, centerPos, Vector3.forward, serie.label.rotate);
p1 = ChartHelper.RotateRound(p1, centerPos, Vector3.forward, serieLabel.rotate);
p2 = ChartHelper.RotateRound(p2, centerPos, Vector3.forward, serieLabel.rotate);
p3 = ChartHelper.RotateRound(p3, centerPos, Vector3.forward, serieLabel.rotate);
p4 = ChartHelper.RotateRound(p4, centerPos, Vector3.forward, serieLabel.rotate);
p5 = ChartHelper.RotateRound(p5, centerPos, Vector3.forward, serieLabel.rotate);
p6 = ChartHelper.RotateRound(p6, centerPos, Vector3.forward, serieLabel.rotate);
p7 = ChartHelper.RotateRound(p7, centerPos, Vector3.forward, serieLabel.rotate);
p8 = ChartHelper.RotateRound(p8, centerPos, Vector3.forward, serieLabel.rotate);
}
ChartDrawer.DrawLine(vh, p1, p2, borderWid, serie.label.borderColor);
ChartDrawer.DrawLine(vh, p3, p4, borderWid, serie.label.borderColor);
ChartDrawer.DrawLine(vh, p5, p6, borderWid, serie.label.borderColor);
ChartDrawer.DrawLine(vh, p7, p8, borderWid, serie.label.borderColor);
ChartDrawer.DrawLine(vh, p1, p2, borderWid, serieLabel.borderColor);
ChartDrawer.DrawLine(vh, p3, p4, borderWid, serieLabel.borderColor);
ChartDrawer.DrawLine(vh, p5, p6, borderWid, serieLabel.borderColor);
ChartDrawer.DrawLine(vh, p7, p8, borderWid, serieLabel.borderColor);
}
}

View File

@@ -90,6 +90,7 @@ namespace XCharts
{
base.DrawChart(vh);
if (!m_CheckMinMaxValue) return;
m_IsPlayingStartAnimation = false;
bool yCategory = m_YAxises[0].IsCategory() || m_YAxises[1].IsCategory();
m_Series.GetStackSeries(ref m_StackSeries);
int seriesCount = m_StackSeries.Count;
@@ -787,7 +788,7 @@ namespace XCharts
{
m_Series.GetYMinMaxValue(m_DataZoom, axisIndex, false, out tempMinValue, out tempMaxValue);
}
axis.AdjustMinMaxValue(ref tempMinValue, ref tempMaxValue);
axis.AdjustMinMaxValue(ref tempMinValue, ref tempMaxValue, true);
if (tempMinValue != axis.runtimeMinValue || tempMaxValue != axis.runtimeMaxValue)
{
m_CheckMinMaxValue = true;
@@ -814,10 +815,17 @@ namespace XCharts
{
float coordinateWidth = axis is XAxis ? this.coordinateWidth : coordinateHeight;
var isPercentStack = m_Series.IsPercentStack(SerieType.Bar);
axis.UpdateLabelText(coordinateWidth, m_DataZoom, isPercentStack);
axis.UpdateLabelText(coordinateWidth, m_DataZoom, isPercentStack, 500);
RefreshChart();
}
}
if (axis.IsValueChanging(500) && !m_IsPlayingStartAnimation)
{
float coordinateWidth = axis is XAxis ? this.coordinateWidth : coordinateHeight;
var isPercentStack = m_Series.IsPercentStack(SerieType.Bar);
axis.UpdateLabelText(coordinateWidth, m_DataZoom, isPercentStack, 500);
RefreshChart();
}
}
protected virtual void OnCoordinateChanged()
@@ -1044,7 +1052,7 @@ namespace XCharts
float minValue = 0;
float maxValue = 0;
m_Series.GetYMinMaxValue(null, 0, IsValue(), out minValue, out maxValue);
axis.AdjustMinMaxValue(ref minValue, ref maxValue);
axis.AdjustMinMaxValue(ref minValue, ref maxValue, true);
int rate = 1;
var sampleDist = serie.sampleDist < 2 ? 2 : serie.sampleDist;
@@ -1053,10 +1061,11 @@ namespace XCharts
if (rate < 1) rate = 1;
var totalAverage = serie.sampleAverage > 0 ? serie.sampleAverage :
DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
var dataChanging = false;
for (int i = 0; i < maxCount; i += rate)
{
float value = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage, i);
float value = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage, i,
serie.animation.GetUpdateAnimationDuration(), ref dataChanging);
float pX = coordinateX + i * scaleWid;
float dataHig = (axis.runtimeMaxValue - axis.runtimeMinValue) == 0 ? 0 :
(value - axis.runtimeMinValue) / (axis.runtimeMaxValue - axis.runtimeMinValue) * hig;
@@ -1074,6 +1083,10 @@ namespace XCharts
}
lp = np;
}
if (dataChanging)
{
RefreshChart();
}
}
switch (m_DataZoom.rangeMode)
{
@@ -1373,7 +1386,7 @@ namespace XCharts
if (j >= serie.dataPoints.Count) break;
var serieData = serie.data[j];
var pos = serie.dataPoints[j];
serieData.SetGameObjectPosition(serieData.labelPosition);
serieData.UpdateIcon();
if (serie.show && serie.label.show && serieData.canShowLabel)

View File

@@ -123,6 +123,7 @@ namespace XCharts
}
}
RefreshChart();
m_IsPlayingStartAnimation = true;
}
return currHig;
}
@@ -155,15 +156,16 @@ namespace XCharts
}
var isPercentStack = m_Series.IsPercentStack(serie.stack, SerieType.Bar);
float updateDuration = serie.animation.GetUpdateAnimationDuration();
bool dataChanging = false;
for (int i = serie.minShow; i < maxCount; i++)
{
if (i >= seriesHig.Count)
{
seriesHig.Add(0);
}
var serieData = showData[i];
serieData.canShowLabel = true;
float value = showData[i].data[1];
float value = showData[i].GetCurrData(1, updateDuration);
if (showData[i].IsDataChanged()) dataChanging = true;
float pX = coordinateX + i * categoryWidth;
float zeroY = coordinateY + yAxis.runtimeZeroYOffset;
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
@@ -213,6 +215,10 @@ namespace XCharts
}
}
}
if (dataChanging)
{
RefreshChart();
}
if (!m_Series.IsStack(serie.stack, SerieType.Bar))
{
m_BarLastOffset += barGapWidth;

View File

@@ -183,6 +183,7 @@ namespace XCharts
float duration = serie.animation.duration > 0 ? (float)serie.animation.duration / 1000 : 1;
float speed = xCount / duration;
serie.animation.CheckProgress(Time.deltaTime * speed);
m_IsPlayingStartAnimation = true;
RefreshChart();
}
}

View File

@@ -111,6 +111,8 @@ namespace XCharts
var includeLastData = false;
var totalAverage = serie.sampleAverage > 0 ? serie.sampleAverage :
DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
var dataChanging = false;
var updateDuration = serie.animation.GetUpdateAnimationDuration();
for (i = serie.minShow; i < maxCount; i += rate)
{
if (i == maxCount - 1) includeLastData = true;
@@ -118,16 +120,23 @@ namespace XCharts
{
for (int j = 0; j < rate; j++) seriesHig.Add(0);
}
float yValue = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage, i);
seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np);
float yValue = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage,
i, updateDuration, ref dataChanging);
seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np,
updateDuration);
serie.dataPoints.Add(np);
}
if (dataChanging)
{
RefreshChart();
}
if (!includeLastData)
{
i = maxCount - 1;
seriesHig.Add(0);
float yValue = showData[i].data[1];
seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np);
float yValue = showData[i].GetCurrData(1, updateDuration);
seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np,
updateDuration);
serie.dataPoints.Add(np);
}
if (serie.dataPoints.Count <= 0)
@@ -144,8 +153,8 @@ namespace XCharts
if (serie.minShow > 0 && serie.minShow < showData.Count)
{
i = serie.minShow - 1;
float yValue = showData[i].data[1];
GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref firstLastPos);
float yValue = showData[i].GetCurrData(1, updateDuration);
GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref firstLastPos, updateDuration);
}
else
{
@@ -154,14 +163,13 @@ namespace XCharts
if (serie.maxShow > 0 && serie.maxShow < showData.Count)
{
i = serie.maxShow;
float yValue = showData[i].data[1];
GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref lastNextPos);
float yValue = showData[i].GetCurrData(1, updateDuration);
GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, 0, ref lastNextPos, updateDuration);
}
else
{
lastNextPos = serie.dataPoints[serie.dataPoints.Count - 1];
}
for (i = 1; i < serie.dataPoints.Count; i++)
{
np = serie.dataPoints[i];
@@ -216,6 +224,7 @@ namespace XCharts
float symbolSpeed = serie.symbol.size / duration;
serie.animation.CheckProgress(Time.deltaTime * speed);
serie.animation.CheckSymbol(Time.deltaTime * symbolSpeed, serie.symbol.size);
m_IsPlayingStartAnimation = true;
RefreshChart();
}
}
@@ -236,9 +245,13 @@ namespace XCharts
}
private float SampleValue(ref List<SerieData> showData, SampleType sampleType, int rate,
int minCount, int maxCount, float totalAverage, int index)
int minCount, int maxCount, float totalAverage, int index, float updateDuration, ref bool dataChanging)
{
if (rate <= 1 || index == minCount) return showData[index].data[1];
if (rate <= 1 || index == minCount)
{
if (showData[index].IsDataChanged()) dataChanging = true;
return showData[index].GetCurrData(1, updateDuration);
}
switch (sampleType)
{
case SampleType.Sum:
@@ -246,7 +259,8 @@ namespace XCharts
float total = 0;
for (int i = index; i > index - rate; i--)
{
total += showData[i].data[1];
total += showData[i].GetCurrData(1, updateDuration);
if (showData[i].IsDataChanged()) dataChanging = true;
}
if (sampleType == SampleType.Average) return total / rate;
else return total;
@@ -254,16 +268,18 @@ namespace XCharts
float max = float.MinValue;
for (int i = index; i > index - rate; i--)
{
var value = showData[i].data[1];
var value = showData[i].GetCurrData(1, updateDuration);
if (value > max) max = value;
if (showData[i].IsDataChanged()) dataChanging = true;
}
return max;
case SampleType.Min:
float min = float.MaxValue;
for (int i = index; i > index - rate; i--)
{
var value = showData[i].data[1];
var value = showData[i].GetCurrData(1, updateDuration);
if (value < min) min = value;
if (showData[i].IsDataChanged()) dataChanging = true;
}
return min;
case SampleType.Peak:
@@ -272,40 +288,45 @@ namespace XCharts
total = 0;
for (int i = index; i > index - rate; i--)
{
var value = showData[i].data[1];
var value = showData[i].GetCurrData(1, updateDuration);
total += value;
if (value < min) min = value;
if (value > max) max = value;
if (showData[i].IsDataChanged()) dataChanging = true;
}
var average = total / rate;
if (average >= totalAverage) return max;
else return min;
}
return showData[index].data[1];
if (showData[index].IsDataChanged()) dataChanging = true;
return showData[index].GetCurrData(1, updateDuration);
}
private float GetDataPoint(Axis xAxis, Axis yAxis, List<SerieData> showData, float yValue, float startX, int i,
float scaleWid, float serieHig, ref Vector3 np)
float scaleWid, float serieHig, ref Vector3 np, float duration)
{
float xDataHig, yDataHig;
float xMinValue = xAxis.GetCurrMinValue(duration);
float xMaxValue = xAxis.GetCurrMaxValue(duration);
float yMinValue = yAxis.GetCurrMinValue(duration);
float yMaxValue = yAxis.GetCurrMaxValue(duration);
if (xAxis.IsValue())
{
float xValue = i > showData.Count - 1 ? 0 : showData[i].data[0];
float pX = coordinateX + xAxis.axisLine.width;
float pY = serieHig + coordinateY + xAxis.axisLine.width;
if ((xAxis.runtimeMaxValue - xAxis.runtimeMinValue) <= 0) xDataHig = 0;
else xDataHig = (xValue - xAxis.runtimeMinValue) / (xAxis.runtimeMaxValue - xAxis.runtimeMinValue) * coordinateWidth;
if ((yAxis.runtimeMaxValue - yAxis.runtimeMinValue) <= 0) yDataHig = 0;
else yDataHig = (yValue - yAxis.runtimeMinValue) / (yAxis.runtimeMaxValue - yAxis.runtimeMinValue) * coordinateHeight;
if ((xMaxValue - xMinValue) <= 0) xDataHig = 0;
else xDataHig = (xValue - xMinValue) / (xMaxValue - xMinValue) * coordinateWidth;
if ((yMaxValue - yMinValue) <= 0) yDataHig = 0;
else yDataHig = (yValue - yMinValue) / (yMaxValue - yMinValue) * coordinateHeight;
np = new Vector3(pX + xDataHig, pY + yDataHig);
}
else
{
float pX = startX + i * scaleWid;
float pY = serieHig + coordinateY + yAxis.axisLine.width;
if ((yAxis.runtimeMaxValue - yAxis.runtimeMinValue) <= 0) yDataHig = 0;
else yDataHig = (yValue - yAxis.runtimeMinValue) / (yAxis.runtimeMaxValue - yAxis.runtimeMinValue) * coordinateHeight;
if ((yMaxValue - yMinValue) <= 0) yDataHig = 0;
else yDataHig = (yValue - yMinValue) / (yMaxValue - yMinValue) * coordinateHeight;
np = new Vector3(pX, pY + yDataHig);
}
return yDataHig;
@@ -442,6 +463,7 @@ namespace XCharts
float symbolSpeed = serie.symbol.size / duration;
serie.animation.CheckProgress(Time.deltaTime * speed);
serie.animation.CheckSymbol(Time.deltaTime * symbolSpeed, serie.symbol.size);
m_IsPlayingStartAnimation = true;
RefreshChart();
}
}

View File

@@ -66,6 +66,7 @@ namespace XCharts
float duration = serie.animation.duration > 0 ? (float)serie.animation.duration / 1000 : 1;
float speed = 1 / duration;
serie.animation.CheckProgress(Time.deltaTime * speed);
m_IsPlayingStartAnimation = true;
RefreshChart();
}
}

View File

@@ -0,0 +1,96 @@
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public class LabelObject
{
private GameObject m_GameObject;
private bool m_LabelAutoSize = true;
private float m_LabelPaddingLeftRight = 3f;
private float m_LabelPaddingTopBottom = 3f;
private Text m_LabelText;
private RectTransform m_LabelRect;
private Image m_IconImage;
private RectTransform m_IconRect;
public Image icon { get { return m_IconImage; } }
public Text label { get { return m_LabelText; } }
public LabelObject()
{
}
public void SetLabel(GameObject labelObj, bool autoSize, float paddingLeftRight, float paddingTopBottom)
{
m_GameObject = labelObj;
m_LabelAutoSize = autoSize;
m_LabelPaddingLeftRight = paddingLeftRight;
m_LabelPaddingTopBottom = paddingTopBottom;
m_LabelText = labelObj.GetComponentInChildren<Text>();
m_LabelRect = m_LabelText.GetComponent<RectTransform>();
}
public void SetIcon(Image image)
{
m_IconImage = image;
if (image != null)
{
m_IconRect = m_IconImage.GetComponent<RectTransform>();
}
}
public void SetIconSprite(Sprite sprite)
{
if (m_IconImage != null) m_IconImage.sprite = sprite;
}
public void SetIconSize(float width, float height)
{
if (m_LabelRect != null) m_LabelRect.sizeDelta = new Vector3(width, height);
}
public void SetIconActive(bool flag)
{
ChartHelper.SetActive(m_IconImage, flag);
}
public void SetPosition(Vector3 position)
{
if (m_GameObject != null)
{
m_GameObject.transform.localPosition = position;
}
}
public void SetActive(bool flag)
{
ChartHelper.SetActive(m_GameObject, flag);
}
public bool SetText(string text)
{
if (m_LabelText && !m_LabelText.text.Equals(text))
{
m_LabelText.text = text;
if (m_LabelAutoSize)
{
var newSize = string.IsNullOrEmpty(text) ? Vector2.zero :
new Vector2(m_LabelText.preferredWidth + m_LabelPaddingLeftRight * 2,
m_LabelText.preferredHeight + m_LabelPaddingTopBottom * 2);
var sizeChange = newSize.x != m_LabelRect.sizeDelta.x || newSize.y != m_LabelRect.sizeDelta.y;
if (sizeChange) m_LabelRect.sizeDelta = newSize;
return sizeChange;
}
}
return false;
}
}
}

View File

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

View File

@@ -15,7 +15,7 @@ namespace XCharts
{
private static readonly Stack<GameObject> m_Stack = new Stack<GameObject>(200);
public static GameObject Get(string name, Transform parent, SerieLabel label, Font font, Color color, SerieData serieData)
public static GameObject Get(string name, Transform parent, SerieLabel label, Font font, Color color, float iconWidth, float iconHeight)
{
GameObject element;
if (m_Stack.Count == 0 || !Application.isPlaying)
@@ -23,7 +23,7 @@ namespace XCharts
element = ChartHelper.AddSerieLabel(name, parent, font,
color, label.backgroundColor, label.fontSize, label.fontStyle, label.rotate,
label.backgroundWidth, label.backgroundHeight);
ChartHelper.AddIcon("Icon", element.transform, serieData.iconStyle.width, serieData.iconStyle.height);
ChartHelper.AddIcon("Icon", element.transform, iconWidth, iconHeight);
}
else
{
@@ -34,7 +34,7 @@ namespace XCharts
var text = element.GetComponentInChildren<Text>();
text.color = color;
text.font = font;
text.fontSize =label.fontSize;
text.fontSize = label.fontSize;
text.fontStyle = label.fontStyle;
ChartHelper.SetActive(element, true);
}

View File

@@ -66,7 +66,7 @@ namespace XCharts
if (serie.pieClickOffset) isClickOffset = true;
serie.runtimePieDataMax = serie.yMax;
serie.runtimePieDataTotal = serie.yTotal;
UpdatePieCenter(serie);
serie.UpdateCenter(chartWidth, chartHeight);
float totalDegree = 360;
float startDegree = 0;
@@ -97,8 +97,8 @@ namespace XCharts
serieData.runtimePieToAngle = startDegree + degree;
serieData.runtimePieOutsideRadius = serie.pieRoseType > 0 ?
serie.runtimePieInsideRadius + (serie.runtimePieOutsideRadius - serie.runtimePieInsideRadius) * value / serie.runtimePieDataMax :
serie.runtimePieOutsideRadius;
serie.runtimeInsideRadius + (serie.runtimeOutsideRadius - serie.runtimeInsideRadius) * value / serie.runtimePieDataMax :
serie.runtimeOutsideRadius;
if (serieData.highlighted)
{
isDataHighlight = true;
@@ -115,11 +115,11 @@ namespace XCharts
float currRad = serieData.runtimePieHalfAngle * Mathf.Deg2Rad;
float currSin = Mathf.Sin(currRad);
float currCos = Mathf.Cos(currRad);
var center = serie.runtimePieCenterPos;
var center = serie.runtimeCenterPos;
serieData.runtimePieCurrAngle = serieData.runtimePieToAngle;
serieData.runtiemPieOffsetCenter = center;
serieData.runtimePieInsideRadius = serie.runtimePieInsideRadius;
serieData.runtimePieInsideRadius = serie.runtimeInsideRadius;
if (serie.animation.CheckDetailBreak(n, serieData.runtimePieToAngle))
{
isFinish = false;
@@ -139,14 +139,19 @@ namespace XCharts
serieData.runtiemPieOffsetCenter = new Vector3(center.x + serieData.runtimePieOffsetRadius * currSin,
center.y + serieData.runtimePieOffsetRadius * currCos);
var drawStartDegree = startDegree + serie.pieSpace;
var drawEndDegree = serieData.runtimePieCurrAngle - serie.pieSpace;
DrawArcShape(vh, serie, serieData, serieData.runtiemPieOffsetCenter, color, ref drawStartDegree, ref drawEndDegree);
ChartDrawer.DrawDoughnut(vh, serieData.runtiemPieOffsetCenter, serieData.runtimePieInsideRadius, serieData.runtimePieOutsideRadius,
color, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, startDegree, serieData.runtimePieCurrAngle);
color, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, drawStartDegree, drawEndDegree);
}
else
{
var drawStartDegree = startDegree + serie.pieSpace;
var drawEndDegree = serieData.runtimePieCurrAngle - serie.pieSpace;
DrawArcShape(vh, serie, serieData, center, color, ref drawStartDegree, ref drawEndDegree);
ChartDrawer.DrawDoughnut(vh, center, serieData.runtimePieInsideRadius, serieData.runtimePieOutsideRadius,
color, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, startDegree, serieData.runtimePieCurrAngle);
color, m_ThemeInfo.backgroundColor, m_Settings.cicleSmoothness, drawStartDegree, drawEndDegree);
}
serieData.canShowLabel = serieData.runtimePieCurrAngle >= serieData.runtimePieHalfAngle;
isDrawPie = true;
@@ -169,15 +174,38 @@ namespace XCharts
raycastTarget = isClickOffset && isDataHighlight;
}
private void DrawArcShape(VertexHelper vh, Serie serie, SerieData serieData, Vector3 centerPos,
Color color, ref float drawStartDegree, ref float drawEndDegree)
{
if (serie.arcShaped)
{
var width = (serieData.runtimePieOutsideRadius - serieData.runtimePieInsideRadius) / 2;
var radius = serieData.runtimePieInsideRadius + width;
var diffDegree = Mathf.Asin(width / radius) * Mathf.Rad2Deg;
drawStartDegree += diffDegree;
drawEndDegree -= diffDegree;
var px = Mathf.Sin(drawStartDegree * Mathf.Deg2Rad) * radius;
var py = Mathf.Cos(drawStartDegree * Mathf.Deg2Rad) * radius;
var pos = new Vector3(px, py) + centerPos;
ChartDrawer.DrawSector(vh, pos, width, color, drawStartDegree + 180, drawStartDegree + 360);
px = Mathf.Sin(drawEndDegree * Mathf.Deg2Rad) * radius;
py = Mathf.Cos(drawEndDegree * Mathf.Deg2Rad) * radius;
pos = new Vector3(px, py) + centerPos;
ChartDrawer.DrawSector(vh, pos, width, color, drawEndDegree, drawEndDegree + 180);
}
}
private void DrawLabelLine(VertexHelper vh)
{
foreach (var serie in m_Series.list)
{
if (serie.type == SerieType.Pie && serie.label.show)
if (serie.type == SerieType.Pie)
{
foreach (var serieData in serie.data)
{
if (serieData.canShowLabel)
var serieLabel = serieData.GetSerieLabel(serie.label);
if (serieLabel.show && serieData.canShowLabel)
{
int colorIndex = m_LegendRealShowName.IndexOf(serieData.name);
Color color = m_ThemeInfo.GetColor(colorIndex);
@@ -192,11 +220,12 @@ namespace XCharts
{
foreach (var serie in m_Series.list)
{
if (serie.type == SerieType.Pie && serie.label.show)
if (serie.type == SerieType.Pie)
{
foreach (var serieData in serie.data)
{
if (serieData.canShowLabel)
var serieLabel = serieData.GetSerieLabel(serie.label);
if (serieLabel.show && serieData.canShowLabel)
{
UpdateLabelPostion(serie, serieData);
DrawLabelBackground(vh, serie, serieData);
@@ -208,88 +237,89 @@ namespace XCharts
private void DrawLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color color)
{
if (serie.label.show
&& serie.label.position == SerieLabel.Position.Outside
&& serie.label.line)
var serieLabel = serieData.GetSerieLabel(serie.label);
if (serieLabel.show
&& serieLabel.position == SerieLabel.Position.Outside
&& serieLabel.line)
{
var insideRadius = serieData.runtimePieInsideRadius;
var outSideRadius = serieData.runtimePieOutsideRadius;
var center = serie.runtimePieCenterPos;
var center = serie.runtimeCenterPos;
var currAngle = serieData.runtimePieHalfAngle;
if (serie.label.lineColor != Color.clear) color = serie.label.lineColor;
else if (serie.label.lineType == SerieLabel.LineType.HorizontalLine) color *= color;
if (serieLabel.lineColor != Color.clear) color = serieLabel.lineColor;
else if (serieLabel.lineType == SerieLabel.LineType.HorizontalLine) color *= color;
float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad);
float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad);
var radius1 = serie.label.lineType == SerieLabel.LineType.HorizontalLine ?
serie.runtimePieOutsideRadius : outSideRadius;
var radius2 = serie.runtimePieOutsideRadius + serie.label.lineLength1;
var radius1 = serieLabel.lineType == SerieLabel.LineType.HorizontalLine ?
serie.runtimeOutsideRadius : outSideRadius;
var radius2 = serie.runtimeOutsideRadius + serieLabel.lineLength1;
var radius3 = insideRadius + (outSideRadius - insideRadius) / 2;
if (radius1 < serie.runtimePieInsideRadius) radius1 = serie.runtimePieInsideRadius;
if (radius1 < serie.runtimeInsideRadius) radius1 = serie.runtimeInsideRadius;
radius1 -= 0.1f;
var pos0 = new Vector3(center.x + radius3 * currSin, center.y + radius3 * currCos);
var pos1 = new Vector3(center.x + radius1 * currSin, center.y + radius1 * currCos);
var pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
float tx, ty;
Vector3 pos3, pos4, pos6;
var horizontalLineCircleRadius = serie.label.lineWidth * 4f;
var horizontalLineCircleRadius = serieLabel.lineWidth * 4f;
var lineCircleDiff = horizontalLineCircleRadius - 0.3f;
if (currAngle < 90)
{
ty = serie.label.lineWidth * Mathf.Cos((90 - currAngle) * Mathf.Deg2Rad);
tx = serie.label.lineWidth * Mathf.Sin((90 - currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x - tx, pos2.y + ty - serie.label.lineWidth);
ty = serieLabel.lineWidth * Mathf.Cos((90 - currAngle) * Mathf.Deg2Rad);
tx = serieLabel.lineWidth * Mathf.Sin((90 - currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x - tx, pos2.y + ty - serieLabel.lineWidth);
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
r4 += serie.label.lineLength1 - lineCircleDiff;
r4 += serieLabel.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.right * lineCircleDiff;
pos4 = pos6 + Vector3.right * r4;
}
else if (currAngle < 180)
{
ty = serie.label.lineWidth * Mathf.Sin((180 - currAngle) * Mathf.Deg2Rad);
tx = serie.label.lineWidth * Mathf.Cos((180 - currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x - tx, pos2.y - ty + serie.label.lineWidth);
ty = serieLabel.lineWidth * Mathf.Sin((180 - currAngle) * Mathf.Deg2Rad);
tx = serieLabel.lineWidth * Mathf.Cos((180 - currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x - tx, pos2.y - ty + serieLabel.lineWidth);
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
r4 += serie.label.lineLength1 - lineCircleDiff;
r4 += serieLabel.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.right * lineCircleDiff;
pos4 = pos6 + Vector3.right * r4;
}
else if (currAngle < 270)
{
ty = serie.label.lineWidth * Mathf.Sin((180 + currAngle) * Mathf.Deg2Rad);
tx = serie.label.lineWidth * Mathf.Cos((180 + currAngle) * Mathf.Deg2Rad);
ty = serieLabel.lineWidth * Mathf.Sin((180 + currAngle) * Mathf.Deg2Rad);
tx = serieLabel.lineWidth * Mathf.Cos((180 + currAngle) * Mathf.Deg2Rad);
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x + tx, pos2.y - ty + serie.label.lineWidth);
pos3 = new Vector3(pos2.x + tx, pos2.y - ty + serieLabel.lineWidth);
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
r4 += serie.label.lineLength1 - lineCircleDiff;
r4 += serieLabel.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.left * lineCircleDiff;
pos4 = pos6 + Vector3.left * r4;
}
else
{
ty = serie.label.lineWidth * Mathf.Cos((90 + currAngle) * Mathf.Deg2Rad);
tx = serie.label.lineWidth * Mathf.Sin((90 + currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x + tx, pos2.y + ty - serie.label.lineWidth);
ty = serieLabel.lineWidth * Mathf.Cos((90 + currAngle) * Mathf.Deg2Rad);
tx = serieLabel.lineWidth * Mathf.Sin((90 + currAngle) * Mathf.Deg2Rad);
pos3 = new Vector3(pos2.x + tx, pos2.y + ty - serieLabel.lineWidth);
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
r4 += serie.label.lineLength1 - lineCircleDiff;
r4 += serieLabel.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.left * lineCircleDiff;
pos4 = pos6 + Vector3.left * r4;
}
var pos5 = new Vector3(currAngle > 180 ? pos3.x - serie.label.lineLength2 : pos3.x + serie.label.lineLength2, pos3.y);
switch (serie.label.lineType)
var pos5 = new Vector3(currAngle > 180 ? pos3.x - serieLabel.lineLength2 : pos3.x + serieLabel.lineLength2, pos3.y);
switch (serieLabel.lineType)
{
case SerieLabel.LineType.BrokenLine:
ChartDrawer.DrawLine(vh, pos1, pos2, serie.label.lineWidth, color);
ChartDrawer.DrawLine(vh, pos3, pos5, serie.label.lineWidth, color);
ChartDrawer.DrawLine(vh, pos1, pos2, serieLabel.lineWidth, color);
ChartDrawer.DrawLine(vh, pos3, pos5, serieLabel.lineWidth, color);
break;
case SerieLabel.LineType.Curves:
ChartDrawer.DrawCurves(vh, pos1, pos5, pos1, pos2, serie.label.lineWidth, color, m_Settings.lineSmoothness);
ChartDrawer.DrawCurves(vh, pos1, pos5, pos1, pos2, serieLabel.lineWidth, color, m_Settings.lineSmoothness);
break;
case SerieLabel.LineType.HorizontalLine:
ChartDrawer.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
ChartDrawer.DrawLine(vh, pos6, pos4, serie.label.lineWidth, color);
ChartDrawer.DrawLine(vh, pos6, pos4, serieLabel.lineWidth, color);
break;
}
}
@@ -335,13 +365,14 @@ namespace XCharts
if (serieData.labelText == null) return;
var currAngle = serieData.runtimePieHalfAngle;
var isHighlight = (serieData.highlighted && serie.emphasis.label.show);
var showLabel = ((serie.label.show || isHighlight) && serieData.canShowLabel);
var serieLabel = serieData.GetSerieLabel(serie.label);
var showLabel = ((serieLabel.show || isHighlight) && serieData.canShowLabel);
if (showLabel || serieData.iconStyle.show)
{
serieData.SetLabelActive(showLabel);
float rotate = 0;
bool isInsidePosition = serie.label.position == SerieLabel.Position.Inside;
if (serie.label.rotate > 0 && isInsidePosition)
bool isInsidePosition = serieLabel.position == SerieLabel.Position.Inside;
if (serieLabel.rotate > 0 && isInsidePosition)
{
if (currAngle > 180) rotate += 270 - currAngle;
else rotate += -(currAngle - 90);
@@ -351,16 +382,16 @@ namespace XCharts
{
if (serie.emphasis.label.color != Color.clear) color = serie.emphasis.label.color;
}
else if (serie.label.color != Color.clear)
else if (serieLabel.color != Color.clear)
{
color = serie.label.color;
color = serieLabel.color;
}
else
{
color = isInsidePosition ? Color.white : serieColor;
}
var fontSize = isHighlight ? serie.emphasis.label.fontSize : serie.label.fontSize;
var fontStyle = isHighlight ? serie.emphasis.label.fontStyle : serie.label.fontStyle;
var fontSize = isHighlight ? serie.emphasis.label.fontSize : serieLabel.fontSize;
var fontStyle = isHighlight ? serie.emphasis.label.fontStyle : serieLabel.fontStyle;
serieData.labelText.color = color;
serieData.labelText.fontSize = fontSize;
@@ -369,15 +400,20 @@ namespace XCharts
serieData.labelRect.transform.localEulerAngles = new Vector3(0, 0, rotate);
UpdateLabelPostion(serie, serieData);
if (!string.IsNullOrEmpty(serie.label.formatter))
if (!string.IsNullOrEmpty(serieLabel.formatter))
{
var value = serieData.data[1];
var total = serie.yTotal;
var content = serie.label.GetFormatterContent(serie.name, serieData.name, value, total);
var content = serieLabel.GetFormatterContent(serie.name, serieData.name, value, total);
if (serieData.SetLabelText(content)) RefreshChart();
}
else
{
if (serieData.SetLabelText(serieData.name)) RefreshChart();
}
serieData.SetGameObjectPosition(serieData.labelPosition);
if (showLabel) serieData.SetLabelPosition(serie.label.offset);
if (showLabel) serieData.SetLabelPosition(serieLabel.offset);
else serieData.SetLabelActive(false);
}
else
{
@@ -394,48 +430,49 @@ namespace XCharts
var offsetRadius = serieData.runtimePieOffsetRadius;
var insideRadius = serieData.runtimePieInsideRadius;
var outsideRadius = serieData.runtimePieOutsideRadius;
switch (serie.label.position)
var serieLabel = serieData.GetSerieLabel(serie.label);
switch (serieLabel.position)
{
case SerieLabel.Position.Center:
serieData.labelPosition = serie.runtimePieCenterPos;
serieData.labelPosition = serie.runtimeCenterPos;
break;
case SerieLabel.Position.Inside:
var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2;
var labelCenter = new Vector2(serie.runtimePieCenterPos.x + labelRadius * Mathf.Sin(currRad),
serie.runtimePieCenterPos.y + labelRadius * Mathf.Cos(currRad));
var labelCenter = new Vector2(serie.runtimeCenterPos.x + labelRadius * Mathf.Sin(currRad),
serie.runtimeCenterPos.y + labelRadius * Mathf.Cos(currRad));
serieData.labelPosition = labelCenter;
break;
case SerieLabel.Position.Outside:
if (serie.label.lineType == SerieLabel.LineType.HorizontalLine)
if (serieLabel.lineType == SerieLabel.LineType.HorizontalLine)
{
var radius1 = serie.runtimePieOutsideRadius;
var radius1 = serie.runtimeOutsideRadius;
var radius3 = insideRadius + (outsideRadius - insideRadius) / 2;
var currSin = Mathf.Sin(currRad);
var currCos = Mathf.Cos(currRad);
var pos0 = new Vector3(serie.runtimePieCenterPos.x + radius3 * currSin, serie.runtimePieCenterPos.y + radius3 * currCos);
var pos0 = new Vector3(serie.runtimeCenterPos.x + radius3 * currSin, serie.runtimeCenterPos.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 += serie.label.lineLength1 + serie.label.lineWidth * 4;
r4 += serieLabel.lineLength1 + serieLabel.lineWidth * 4;
r4 += serieData.labelText.preferredWidth / 2;
serieData.labelPosition = pos0 + (currAngle > 180 ? Vector3.left : Vector3.right) * r4;
}
else
{
labelRadius = serie.runtimePieOutsideRadius + serie.label.lineLength1;
labelCenter = new Vector2(serie.runtimePieCenterPos.x + labelRadius * Mathf.Sin(currRad),
serie.runtimePieCenterPos.y + labelRadius * Mathf.Cos(currRad));
labelRadius = serie.runtimeOutsideRadius + serieLabel.lineLength1;
labelCenter = new Vector2(serie.runtimeCenterPos.x + labelRadius * Mathf.Sin(currRad),
serie.runtimeCenterPos.y + labelRadius * Mathf.Cos(currRad));
float labelWidth = serieData.labelText.preferredWidth;
if (currAngle > 180)
{
serieData.labelPosition = new Vector2(labelCenter.x - serie.label.lineLength2 - 5 - labelWidth / 2, labelCenter.y);
serieData.labelPosition = new Vector2(labelCenter.x - serieLabel.lineLength2 - 5 - labelWidth / 2, labelCenter.y);
}
else
{
serieData.labelPosition = new Vector2(labelCenter.x + serie.label.lineLength2 + 5 + labelWidth / 2, labelCenter.y);
serieData.labelPosition = new Vector2(labelCenter.x + serieLabel.lineLength2 + 5 + labelWidth / 2, labelCenter.y);
}
}
break;
@@ -464,17 +501,6 @@ namespace XCharts
RefreshChart();
}
private void UpdatePieCenter(Serie serie)
{
if (serie.pieCenter.Length < 2) return;
var centerX = serie.pieCenter[0] <= 1 ? chartWidth * serie.pieCenter[0] : serie.pieCenter[0];
var centerY = serie.pieCenter[1] <= 1 ? chartHeight * serie.pieCenter[1] : serie.pieCenter[1];
serie.runtimePieCenterPos = new Vector2(centerX, centerY);
var minWidth = Mathf.Min(chartWidth, chartHeight);
serie.runtimePieInsideRadius = serie.pieRadius[0] <= 1 ? minWidth * serie.pieRadius[0] : serie.pieRadius[0];
serie.runtimePieOutsideRadius = serie.pieRadius[1] <= 1 ? minWidth * serie.pieRadius[1] : serie.pieRadius[1];
}
protected override void CheckTootipArea(Vector2 local)
{
if (m_IsEnterLegendButtom) return;
@@ -510,9 +536,9 @@ namespace XCharts
private int GetPosPieIndex(Serie serie, Vector2 local)
{
if (serie.type != SerieType.Pie) return -1;
var dist = Vector2.Distance(local, serie.runtimePieCenterPos);
if (dist < serie.runtimePieInsideRadius || dist > serie.runtimePieOutsideRadius) return -1;
Vector2 dir = local - new Vector2(serie.runtimePieCenterPos.x, serie.runtimePieCenterPos.y);
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
if (dist < serie.runtimeInsideRadius || dist > serie.runtimeOutsideRadius) return -1;
Vector2 dir = local - new Vector2(serie.runtimeCenterPos.x, serie.runtimeCenterPos.y);
float angle = VectorAngle(Vector2.up, dir);
for (int i = 0; i < serie.data.Count; i++)
{

View File

@@ -41,6 +41,18 @@ namespace XCharts
SetActive(gameObject.transform, active);
}
public static void SetActive(Image image, bool active)
{
if (image == null) return;
SetActive(image.gameObject, active);
}
public static void SetActive(Text text, bool active)
{
if (text == null) return;
SetActive(text.gameObject, active);
}
/// <summary>
/// 通过设置scale实现是否显示优化性能减少GC
/// </summary>
@@ -357,6 +369,16 @@ namespace XCharts
color1.r == color2.r;
}
public static bool IsValueEqualsVector2(Vector2 v1, Vector2 v2)
{
return v1.x == v2.x && v1.y == v2.y;
}
public static bool IsValueEqualsVector3(Vector3 v1, Vector3 v2)
{
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
}
public static bool IsValueEqualsList<T>(List<T> list1, List<T> list2)
{
if (list1 == null || list2 == null) return false;
@@ -586,5 +608,13 @@ namespace XCharts
Vector3 resultVec3 = center + point;
return resultVec3;
}
public static Vector3 GetPosition(Vector3 center, float angle, float radius)
{
var rad = angle * Mathf.Deg2Rad;
var px = Mathf.Sin(rad) * radius;
var py = Mathf.Cos(rad) * radius;
return center + new Vector3(px, py);
}
}
}