Files
XCharts/Scripts/UI/Internal/CoordinateChart.cs

504 lines
18 KiB
C#
Raw Normal View History

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text;
using System;
namespace XCharts
{
public class CoordinateChart : BaseChart
{
private static readonly string s_DefaultSplitNameY = "split_y";
private static readonly string s_DefaultSplitNameX = "split_x";
[SerializeField] protected Coordinate m_Coordinate = Coordinate.defaultCoordinate;
[SerializeField] protected XAxis m_XAxis = XAxis.defaultXAxis;
[SerializeField] protected YAxis m_YAxis = YAxis.defaultYAxis;
2019-05-13 09:48:47 +08:00
private float m_ZeroXOffset;
private float m_ZeroYOffset;
private XAxis m_CheckXAxis = XAxis.defaultXAxis;
private YAxis m_CheckYAxis = YAxis.defaultYAxis;
private Coordinate m_CheckCoordinate = Coordinate.defaultCoordinate;
private List<Text> m_SplitYTextList = new List<Text>();
private List<Text> m_SplitXTextList = new List<Text>();
public int minValue { get; private set; }
public int maxValue { get; private set; }
public float zeroX { get { return coordinateX + m_ZeroXOffset; } }
public float zeroY { get { return coordinateY + m_ZeroYOffset; } }
public float coordinateX { get { return m_Coordinate.left; } }
public float coordinateY { get { return m_Coordinate.bottom; } }
public float coordinateWid { get { return chartWidth - m_Coordinate.left - m_Coordinate.right; } }
public float coordinateHig { get { return chartHeight - m_Coordinate.top - m_Coordinate.bottom; } }
public Axis xAxis { get { return m_XAxis; } }
public Axis yAxis { get { return m_YAxis; } }
protected override void Awake()
{
base.Awake();
2019-05-13 09:48:47 +08:00
CheckMinMaxValue();
InitSplitX();
InitSplitY();
}
protected override void Update()
{
base.Update();
CheckYAxis();
CheckXAxis();
2019-05-13 09:48:47 +08:00
CheckMinMaxValue();
CheckCoordinate();
}
protected override void Reset()
{
base.Reset();
m_Coordinate = Coordinate.defaultCoordinate;
m_XAxis = XAxis.defaultXAxis;
m_YAxis = YAxis.defaultYAxis;
InitSplitX();
InitSplitY();
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
DrawCoordinate(vh);
}
protected override void CheckTootipArea(Vector2 local)
{
if (local.x < zeroX || local.x > zeroX + coordinateWid ||
local.y < zeroY || local.y > zeroY + coordinateHig)
{
m_Tooltip.dataIndex = 0;
RefreshTooltip();
}
else
{
if (m_XAxis.type == Axis.AxisType.Value)
{
float splitWid = m_YAxis.GetDataWidth(coordinateHig);
for (int i = 0; i < m_YAxis.GetDataNumber(); i++)
{
float pY = zeroY + i * splitWid;
if (m_YAxis.boundaryGap)
{
if (local.y > pY && local.y <= pY + splitWid)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
else
{
if (local.y > pY - splitWid / 2 && local.y <= pY + splitWid / 2)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
}
}
else
{
float splitWid = m_XAxis.GetDataWidth(coordinateWid);
for (int i = 0; i < m_XAxis.GetDataNumber(); i++)
{
float pX = zeroX + i * splitWid;
if (m_XAxis.boundaryGap)
{
if (local.x > pX && local.x <= pX + splitWid)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
else
{
if (local.x > pX - splitWid / 2 && local.x <= pX + splitWid / 2)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
}
}
}
if (m_Tooltip.dataIndex > 0)
{
m_Tooltip.UpdatePos(new Vector2(local.x + 18, local.y - 25));
RefreshTooltip();
if (m_Tooltip.lastDataIndex != m_Tooltip.dataIndex)
{
RefreshChart();
}
m_Tooltip.lastDataIndex = m_Tooltip.dataIndex;
}
}
protected override void RefreshTooltip()
{
base.RefreshTooltip();
int index = m_Tooltip.dataIndex - 1;
Axis tempAxis = m_XAxis.type == Axis.AxisType.Value ? (Axis)m_YAxis : (Axis)m_XAxis;
if (index < 0)
{
m_Tooltip.SetActive(false);
return;
}
m_Tooltip.SetActive(true);
if (m_Series.Count == 1)
{
string txt = tempAxis.GetData(index) + ": " + m_Series.GetData(0,index);
m_Tooltip.UpdateTooltipText(txt);
}
else
{
StringBuilder sb = new StringBuilder(tempAxis.GetData(index));
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Series.series[i].show)
{
string strColor = ColorUtility.ToHtmlStringRGBA(m_ThemeInfo.GetColor(i));
string key = m_Series.series[i].name;
float value = m_Series.series[i].data[index];
sb.Append("\n");
sb.AppendFormat("<color=#{0}>● </color>", strColor);
sb.AppendFormat("{0}: {1}", key, value);
}
}
m_Tooltip.UpdateTooltipText(sb.ToString());
}
var pos = m_Tooltip.GetPos();
if (pos.x + m_Tooltip.width > chartWidth)
{
pos.x = chartWidth - m_Tooltip.width;
}
if (pos.y - m_Tooltip.height < 0)
{
pos.y = m_Tooltip.height;
}
m_Tooltip.UpdatePos(pos);
}
TextGenerationSettings GetTextSetting()
{
var setting = new TextGenerationSettings();
var fontdata = FontData.defaultFontData;
//setting.generationExtents = rectTransform.rect.size;
setting.generationExtents = new Vector2(200.0F, 50.0F);
setting.fontSize = 14;
setting.textAnchor = TextAnchor.MiddleCenter;
setting.scaleFactor = 1f;
setting.color = Color.red;
setting.font = m_ThemeInfo.font;
setting.pivot = new Vector2(0.5f, 0.5f);
setting.richText = false;
setting.lineSpacing = 0;
setting.fontStyle = FontStyle.Normal;
setting.resizeTextForBestFit = false;
setting.horizontalOverflow = HorizontalWrapMode.Overflow;
setting.verticalOverflow = VerticalWrapMode.Overflow;
return setting;
}
protected override void OnThemeChanged()
{
base.OnThemeChanged();
InitSplitX();
InitSplitY();
}
public void AddXAxisData(string category)
{
m_XAxis.AddData(category,m_MaxCacheDataNumber);
OnXAxisChanged();
}
public void AddYAxisData(string category)
{
m_YAxis.AddData(category, m_MaxCacheDataNumber);
OnYAxisChanged();
}
private void InitSplitY()
{
m_SplitYTextList.Clear();
float splitWidth = m_YAxis.GetScaleWidth(coordinateHig);
var titleObject = ChartHelper.AddObject(s_DefaultSplitNameY, transform, chartAnchorMin,
chartAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
titleObject.transform.localPosition = Vector3.zero;
ChartHelper.HideAllObject(titleObject, s_DefaultSplitNameY);
for (int i = 0; i < m_YAxis.splitNumber; i++)
{
Text txt = ChartHelper.AddTextObject(s_DefaultSplitNameY + i, titleObject.transform,
m_ThemeInfo.font, m_ThemeInfo.textColor, TextAnchor.MiddleRight, Vector2.zero,
Vector2.zero, new Vector2(1, 0.5f), new Vector2(m_Coordinate.left, 20),
m_Coordinate.fontSize, m_XAxis.textRotation);
txt.transform.localPosition = GetSplitYPosition(splitWidth, i);
2019-05-13 09:48:47 +08:00
txt.text = m_YAxis.GetScaleName(i, minValue, maxValue);
txt.gameObject.SetActive(m_YAxis.show);
m_SplitYTextList.Add(txt);
}
}
public void InitSplitX()
{
m_SplitXTextList.Clear();
float splitWidth = m_XAxis.GetScaleWidth(coordinateWid);
var titleObject = ChartHelper.AddObject(s_DefaultSplitNameX, transform, chartAnchorMin,
chartAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
titleObject.transform.localPosition = Vector3.zero;
ChartHelper.HideAllObject(titleObject, s_DefaultSplitNameX);
for (int i = 0; i < m_XAxis.splitNumber; i++)
{
Text txt = ChartHelper.AddTextObject(s_DefaultSplitNameX + i, titleObject.transform,
m_ThemeInfo.font, m_ThemeInfo.textColor, TextAnchor.MiddleCenter, Vector2.zero,
Vector2.zero, new Vector2(1, 0.5f), new Vector2(splitWidth, 20),
m_Coordinate.fontSize, m_XAxis.textRotation);
txt.transform.localPosition = GetSplitXPosition(splitWidth, i);
2019-05-13 09:48:47 +08:00
txt.text = m_XAxis.GetScaleName(i, minValue, maxValue);
txt.gameObject.SetActive(m_XAxis.show);
m_SplitXTextList.Add(txt);
}
}
private Vector3 GetSplitYPosition(float scaleWid, int i)
{
if (m_YAxis.boundaryGap)
{
2019-05-13 09:48:47 +08:00
return new Vector3(coordinateX - m_YAxis.axisTick.length - 2f,
coordinateY + (i + 0.5f) * scaleWid, 0);
}
else
{
2019-05-13 09:48:47 +08:00
return new Vector3(coordinateX - m_YAxis.axisTick.length - 2f,
coordinateY + i * scaleWid, 0);
}
}
private Vector3 GetSplitXPosition(float scaleWid, int i)
{
if (m_XAxis.boundaryGap)
{
2019-05-13 09:48:47 +08:00
return new Vector3(coordinateX + (i + 1) * scaleWid, coordinateY - m_XAxis.axisTick.length - 5, 0);
}
else
{
2019-05-13 09:48:47 +08:00
return new Vector3(coordinateX + (i + 1 - 0.5f) * scaleWid,
coordinateY - m_XAxis.axisTick.length - 10, 0);
}
}
private void CheckCoordinate()
{
if (m_CheckCoordinate != m_Coordinate)
{
m_CheckCoordinate.Copy(m_Coordinate);
OnCoordinateChanged();
}
}
private void CheckYAxis()
{
if (m_CheckYAxis != m_YAxis)
{
m_CheckYAxis.Copy(m_YAxis);
OnYAxisChanged();
}
}
private void CheckXAxis()
{
if (!m_CheckXAxis.Equals(m_XAxis))
{
m_CheckXAxis.Copy(m_XAxis);
OnXAxisChanged();
}
}
2019-05-13 09:48:47 +08:00
private void CheckMinMaxValue()
{
2019-05-13 09:48:47 +08:00
int tempMinValue = 0;
int tempMaxValue = 100;
if(m_Series != null)
{
m_Series.GetMinMaxValue(m_Legend, out tempMinValue, out tempMaxValue);
}
if (tempMinValue != minValue || tempMaxValue != maxValue)
{
2019-05-13 09:48:47 +08:00
minValue = tempMinValue;
maxValue = tempMaxValue;
if (m_XAxis.type == Axis.AxisType.Value)
{
2019-05-13 09:48:47 +08:00
m_ZeroXOffset = Mathf.Abs(minValue) * (coordinateWid / (Mathf.Abs(minValue) + Mathf.Abs(maxValue)));
OnXMaxValueChanged();
}
2019-05-13 09:48:47 +08:00
else if (m_YAxis.type == Axis.AxisType.Value)
{
2019-05-13 09:48:47 +08:00
m_ZeroYOffset = Mathf.Abs(minValue) * (coordinateHig / (Mathf.Abs(minValue) + Mathf.Abs(maxValue)));
OnYMaxValueChanged();
}
2019-05-13 09:48:47 +08:00
RefreshChart();
}
}
protected virtual void OnCoordinateChanged()
{
InitSplitX();
InitSplitY();
}
protected virtual void OnYAxisChanged()
{
InitSplitY();
}
protected virtual void OnXAxisChanged()
{
InitSplitX();
}
protected override void OnSizeChanged()
{
base.OnSizeChanged();
InitSplitX();
InitSplitY();
}
protected override void OnYMaxValueChanged()
{
for (int i = 0; i < m_SplitYTextList.Count; i++)
{
2019-05-13 09:48:47 +08:00
m_SplitYTextList[i].text = m_YAxis.GetScaleName(i, minValue, maxValue);
}
}
protected virtual void OnXMaxValueChanged()
{
for (int i = 0; i < m_SplitXTextList.Count; i++)
{
m_SplitXTextList[i].text = m_XAxis.GetScaleName(i, minValue, maxValue);
}
}
private void DrawCoordinate(VertexHelper vh)
{
#region draw tick and splitline
if (m_YAxis.show)
{
2019-05-13 09:48:47 +08:00
for (int i = 0; i < m_YAxis.GetScaleNumber(); i++)
{
2019-05-13 09:48:47 +08:00
float pX = coordinateX - m_YAxis.axisTick.length;
float pY = coordinateY + i * m_YAxis.GetScaleWidth(coordinateHig);
if (m_YAxis.boundaryGap && m_YAxis.axisTick.alignWithLabel)
{
pY -= m_YAxis.GetScaleWidth(coordinateHig) / 2;
}
if (m_YAxis.axisTick.show)
{
2019-05-13 09:48:47 +08:00
ChartHelper.DrawLine(vh, new Vector3(pX, pY), new Vector3(coordinateX, pY),
m_Coordinate.tickness, m_ThemeInfo.axisLineColor);
}
if (m_YAxis.showSplitLine)
{
2019-05-13 09:48:47 +08:00
DrawSplitLine(vh, true, m_YAxis.splitLineType, new Vector3(coordinateX, pY),
new Vector3(coordinateX + coordinateWid, pY));
}
}
}
if (m_XAxis.show)
{
2019-05-13 09:48:47 +08:00
for (int i = 0; i < m_XAxis.GetScaleNumber(); i++)
{
2019-05-13 09:48:47 +08:00
float pX = coordinateX + i * m_XAxis.GetScaleWidth(coordinateWid);
float pY = 0;
if (m_XAxis.boundaryGap && m_XAxis.axisTick.alignWithLabel)
{
pX -= m_XAxis.GetScaleWidth(coordinateWid) / 2;
}
if (m_XAxis.axisTick.show)
{
2019-05-13 09:48:47 +08:00
pY += zeroY - m_XAxis.axisTick.length - 2;
ChartHelper.DrawLine(vh, new Vector3(pX, zeroY), new Vector3(pX, pY), m_Coordinate.tickness,
m_ThemeInfo.axisLineColor);
}
if (m_XAxis.showSplitLine)
{
2019-05-13 09:48:47 +08:00
pY += coordinateY - m_XAxis.axisTick.length - 2;
DrawSplitLine(vh, false, m_XAxis.splitLineType, new Vector3(pX, coordinateY),
new Vector3(pX, coordinateY + coordinateHig));
}
}
}
#endregion
2019-05-13 09:48:47 +08:00
#region draw x,y axis
if (m_YAxis.show)
{
2019-05-13 09:48:47 +08:00
ChartHelper.DrawLine(vh, new Vector3(coordinateX, coordinateY),
new Vector3(coordinateX, coordinateY + coordinateHig), m_Coordinate.tickness,
m_ThemeInfo.axisLineColor);
}
if (m_XAxis.show)
{
ChartHelper.DrawLine(vh, new Vector3(zeroX - m_XAxis.axisTick.length, zeroY),
2019-05-13 09:48:47 +08:00
new Vector3(zeroX + coordinateWid + 2, zeroY), m_Coordinate.tickness,
m_ThemeInfo.axisLineColor);
}
2019-05-13 09:48:47 +08:00
#endregion
}
private void DrawSplitLine(VertexHelper vh, bool isYAxis, Axis.SplitLineType type, Vector3 startPos,
Vector3 endPos)
{
switch (type)
{
case Axis.SplitLineType.Dashed:
case Axis.SplitLineType.Dotted:
var startX = startPos.x;
var startY = startPos.y;
var dashLen = type == Axis.SplitLineType.Dashed ? 6 : 2.5f;
var count = isYAxis ? (endPos.x - startPos.x) / (dashLen * 2) :
(endPos.y - startPos.y) / (dashLen * 2);
for (int i = 0; i < count; i++)
{
if (isYAxis)
{
var toX = startX + dashLen;
ChartHelper.DrawLine(vh, new Vector3(startX, startY), new Vector3(toX, startY),
m_Coordinate.tickness, m_ThemeInfo.axisSplitLineColor);
startX += dashLen * 2;
}
else
{
var toY = startY + dashLen;
ChartHelper.DrawLine(vh, new Vector3(startX, startY), new Vector3(startX, toY),
m_Coordinate.tickness, m_ThemeInfo.axisSplitLineColor);
startY += dashLen * 2;
}
}
break;
case Axis.SplitLineType.Solid:
ChartHelper.DrawLine(vh, startPos, endPos, m_Coordinate.tickness,
m_ThemeInfo.axisSplitLineColor);
break;
}
}
}
}