mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-26 10:50:08 +00:00
3.0 - unitypackage
This commit is contained in:
8
Runtime/Serie/Bar.meta
Normal file
8
Runtime/Serie/Bar.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db4db63725f6848e785146f5cf4bb657
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Runtime/Serie/Bar/Bar.cs
Normal file
37
Runtime/Serie/Bar/Bar.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(BarHandler), true)]
|
||||
[SerieConvert(typeof(Line), typeof(Pie))]
|
||||
[RequireChartComponent(typeof(GridCoord))]
|
||||
[DefaultAnimation(AnimationType.BottomToTop)]
|
||||
[SerieExtraComponent(
|
||||
typeof(LabelStyle),
|
||||
typeof(IconStyle),
|
||||
typeof(Emphasis))]
|
||||
public class Bar : Serie, INeedSerieContainer, ISimplifiedSerie
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Bar>(serieName);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
chart.AddData(serie.index, UnityEngine.Random.Range(10, 90));
|
||||
}
|
||||
}
|
||||
|
||||
public static Bar CovertSerie(Serie serie)
|
||||
{
|
||||
var newSerie = SerieHelper.CloneSerie<Bar>(serie);
|
||||
return newSerie;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Bar/Bar.cs.meta
Normal file
11
Runtime/Serie/Bar/Bar.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfb8051cfc49e4afabd94a11c5912c3e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
640
Runtime/Serie/Bar/BarHandler.cs
Normal file
640
Runtime/Serie/Bar/BarHandler.cs
Normal file
@@ -0,0 +1,640 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class BarHandler : SerieHandler<Bar>
|
||||
{
|
||||
List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
|
||||
private GridCoord m_SerieGrid;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
|
||||
marker, itemFormatter, numericFormatter);
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
DrawBarSerie(vh, serie, serie.context.colorIndex);
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
|
||||
var needInteract = false;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag != needCheck)
|
||||
{
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
if (m_LegendEnter)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.context.rect.Contains(chart.pointerPos))
|
||||
{
|
||||
serie.context.pointerItemDataIndex = serieData.index;
|
||||
serie.context.pointerEnter = true;
|
||||
serieData.context.highlight = true;
|
||||
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBarSerie(VertexHelper vh, Bar serie, int colorIndex)
|
||||
{
|
||||
if (!serie.show || serie.animation.HasFadeOut())
|
||||
return;
|
||||
|
||||
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
|
||||
|
||||
Axis axis;
|
||||
Axis relativedAxis;
|
||||
|
||||
if (isY)
|
||||
{
|
||||
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
}
|
||||
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
|
||||
|
||||
if (axis == null)
|
||||
return;
|
||||
if (relativedAxis == null)
|
||||
return;
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
|
||||
if (showData.Count <= 0)
|
||||
return;
|
||||
|
||||
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
|
||||
var axisXY = isY ? m_SerieGrid.context.y : m_SerieGrid.context.x;
|
||||
|
||||
var isStack = SeriesHelper.IsStack<Bar>(chart.series, serie.stack);
|
||||
if (isStack)
|
||||
SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
|
||||
|
||||
float categoryWidth = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
|
||||
float barGap = chart.GetSerieBarGap<Bar>();
|
||||
float totalBarWidth = chart.GetSerieTotalWidth<Bar>(categoryWidth, barGap);
|
||||
float barWidth = serie.GetBarWidth(categoryWidth);
|
||||
float offset = (categoryWidth - totalBarWidth) * 0.5f;
|
||||
float barGapWidth = barWidth + barWidth * barGap;
|
||||
float space = serie.barGap == -1 ? offset : offset + chart.GetSerieIndexIfStack<Bar>(serie) * barGapWidth;
|
||||
int maxCount = serie.maxShow > 0
|
||||
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
|
||||
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(chart.series, serie.stack);
|
||||
bool dataChanging = false;
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
double yMinValue = relativedAxis.context.minValue;
|
||||
double yMaxValue = relativedAxis.context.maxValue;
|
||||
|
||||
var areaColor = ColorUtil.clearColor32;
|
||||
var areaToColor = ColorUtil.clearColor32;
|
||||
var interacting = false;
|
||||
|
||||
serie.containerIndex = m_SerieGrid.index;
|
||||
serie.containterInstanceId = m_SerieGrid.instanceId;
|
||||
serie.animation.InitProgress(axisXY, axisXY + axisLength);
|
||||
for (int i = serie.minShow; i < maxCount; i++)
|
||||
{
|
||||
var serieData = showData[i];
|
||||
if (!serieData.show || serie.IsIgnoreValue(serieData))
|
||||
{
|
||||
serie.context.dataPoints.Add(Vector3.zero);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (serieData.IsDataChanged())
|
||||
dataChanging = true;
|
||||
|
||||
var highlight = serieData.context.highlight || serie.highlight;
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
|
||||
var value = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
|
||||
var relativedValue = serieData.GetCurrData(1, dataChangeDuration, relativedAxis.inverse, yMinValue, yMaxValue);
|
||||
var borderWidth = relativedValue == 0 ? 0 : itemStyle.runtimeBorderWidth;
|
||||
|
||||
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting))
|
||||
{
|
||||
areaColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, highlight);
|
||||
areaToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, highlight);
|
||||
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
|
||||
}
|
||||
|
||||
var pX = 0f;
|
||||
var pY = 0f;
|
||||
UpdateXYPosition(m_SerieGrid, isY, axis, relativedAxis, i, categoryWidth, barWidth, isStack, value, ref pX, ref pY);
|
||||
|
||||
var barHig = 0f;
|
||||
if (isPercentStack)
|
||||
{
|
||||
var valueTotal = chart.GetSerieSameStackTotalValue<Bar>(serie.stack, i);
|
||||
barHig = valueTotal != 0 ? (float)(relativedValue / valueTotal * axisLength) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
barHig = AxisHelper.GetAxisValueLength(m_SerieGrid, relativedAxis, categoryWidth, relativedValue);
|
||||
}
|
||||
|
||||
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
|
||||
|
||||
Vector3 plb, plt, prt, prb, top;
|
||||
UpdateRectPosition(m_SerieGrid, isY, relativedValue, pX, pY, space, borderWidth, barWidth, currHig,
|
||||
out plb, out plt, out prt, out prb, out top);
|
||||
serieData.context.stackHeight = barHig;
|
||||
serieData.context.position = top;
|
||||
serieData.context.rect = Rect.MinMaxRect(plb.x, plb.y, prb.x, prt.y);
|
||||
serie.context.dataPoints.Add(top);
|
||||
if (serie.show && currHig != 0)
|
||||
{
|
||||
switch (serie.barType)
|
||||
{
|
||||
case BarType.Normal:
|
||||
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, m_SerieGrid, areaColor, areaToColor);
|
||||
break;
|
||||
case BarType.Zebra:
|
||||
DrawZebraBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, m_SerieGrid, areaColor, areaToColor);
|
||||
break;
|
||||
case BarType.Capsule:
|
||||
DrawCapsuleBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, m_SerieGrid, areaColor, areaToColor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (serie.animation.CheckDetailBreak(top, isY))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging || interacting)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateXYPosition(GridCoord grid, bool isY, Axis axis, Axis relativedAxis, int i, float categoryWidth, float barWidth, bool isStack,
|
||||
double value, ref float pX, ref float pY)
|
||||
{
|
||||
if (isY)
|
||||
{
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
pY = grid.context.y + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (axis.context.minMaxRange <= 0) pY = grid.context.y;
|
||||
else pY = grid.context.y + (float)((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.height - barWidth);
|
||||
}
|
||||
pX = AxisHelper.GetAxisPosition(grid, relativedAxis, categoryWidth, 0);
|
||||
if (isStack)
|
||||
{
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
pX += m_StackSerieData[n][i].context.stackHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
pX = grid.context.x + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (axis.context.minMaxRange <= 0) pX = grid.context.x;
|
||||
else pX = grid.context.x + (float)((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.width - barWidth);
|
||||
}
|
||||
pY = AxisHelper.GetAxisPosition(grid, relativedAxis, categoryWidth, 0);
|
||||
if (isStack)
|
||||
{
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
pY += m_StackSerieData[n][i].context.stackHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRectPosition(GridCoord grid, bool isY, double yValue, float pX, float pY, float space, float borderWidth,
|
||||
float barWidth, float currHig,
|
||||
out Vector3 plb, out Vector3 plt, out Vector3 prt, out Vector3 prb, out Vector3 top)
|
||||
{
|
||||
if (isY)
|
||||
{
|
||||
if (yValue < 0)
|
||||
{
|
||||
plt = new Vector3(pX - borderWidth, pY + space + barWidth - borderWidth);
|
||||
prt = new Vector3(pX + currHig + borderWidth, pY + space + barWidth - borderWidth);
|
||||
prb = new Vector3(pX + currHig + borderWidth, pY + space + borderWidth);
|
||||
plb = new Vector3(pX - borderWidth, pY + space + borderWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
plt = new Vector3(pX + borderWidth, pY + space + barWidth - borderWidth);
|
||||
prt = new Vector3(pX + currHig - borderWidth, pY + space + barWidth - borderWidth);
|
||||
prb = new Vector3(pX + currHig - borderWidth, pY + space + borderWidth);
|
||||
plb = new Vector3(pX + borderWidth, pY + space + borderWidth);
|
||||
}
|
||||
top = new Vector3(pX + currHig - borderWidth, pY + space + barWidth / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yValue < 0)
|
||||
{
|
||||
plb = new Vector3(pX + space + borderWidth, pY - borderWidth);
|
||||
plt = new Vector3(pX + space + borderWidth, pY + currHig + borderWidth);
|
||||
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig + borderWidth);
|
||||
prb = new Vector3(pX + space + barWidth - borderWidth, pY - borderWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
|
||||
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
|
||||
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
|
||||
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
|
||||
}
|
||||
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
|
||||
}
|
||||
if (serie.clip)
|
||||
{
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
top = chart.ClampInGrid(grid, top);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, GridCoord grid, Color32 areaColor, Color32 areaToColor)
|
||||
{
|
||||
|
||||
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
|
||||
var borderWidth = itemStyle.runtimeBorderWidth;
|
||||
if (isYAxis)
|
||||
{
|
||||
if (serie.clip)
|
||||
{
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
}
|
||||
var itemWidth = Mathf.Abs(prb.x - plt.x);
|
||||
var itemHeight = Mathf.Abs(prt.y - plb.y);
|
||||
var center = new Vector3((plt.x + prb.x) / 2, (prt.y + plb.y) / 2);
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
var invert = center.x < plb.x;
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, plb, plt, prt, prb, areaColor, areaToColor, serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
|
||||
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serie.clip)
|
||||
{
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
}
|
||||
var itemWidth = Mathf.Abs(prt.x - plb.x);
|
||||
var itemHeight = Mathf.Abs(plt.y - prb.y);
|
||||
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
var invert = center.y < plb.y;
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaToColor,
|
||||
serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
|
||||
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawZebraBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, GridCoord grid, Color32 barColor, Color32 barToColor)
|
||||
{
|
||||
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
|
||||
if (isYAxis)
|
||||
{
|
||||
plt = (plb + plt) / 2;
|
||||
prt = (prt + prb) / 2;
|
||||
chart.DrawClipZebraLine(vh, plt, prt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
|
||||
barColor, barToColor, serie.clip, grid);
|
||||
}
|
||||
else
|
||||
{
|
||||
plb = (prb + plb) / 2;
|
||||
plt = (plt + prt) / 2;
|
||||
chart.DrawClipZebraLine(vh, plb, plt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
|
||||
barColor, barToColor, serie.clip, grid);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCapsuleBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, GridCoord grid, Color32 areaColor, Color32 areaToColor)
|
||||
{
|
||||
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
|
||||
var borderWidth = itemStyle.runtimeBorderWidth;
|
||||
var radius = barWidth / 2 - borderWidth;
|
||||
var isGradient = !ChartHelper.IsValueEqualsColor(areaColor, areaToColor);
|
||||
if (isYAxis)
|
||||
{
|
||||
var diff = Vector3.right * radius;
|
||||
if (plt.x < prt.x)
|
||||
{
|
||||
var pcl = (plt + plb) / 2 + diff;
|
||||
var pcr = (prt + prb) / 2 - diff;
|
||||
if (pcr.x > pcl.x)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = prt.x - plt.x;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
chart.DrawClipPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, areaColor, rectStartColor, 180, 360, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcr, radius, rectEndColor, areaToColor, 0, 180, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, areaColor, 180, 360);
|
||||
UGL.DrawSector(vh, pcr, radius, areaToColor, 0, 180);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (plt.x > prt.x)
|
||||
{
|
||||
var pcl = (plt + plb) / 2 - diff;
|
||||
var pcr = (prt + prb) / 2 + diff;
|
||||
if (pcr.x < pcl.x)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = plt.x - prt.x;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
chart.DrawClipPolygon(vh, plb - diff, plt - diff, prt + diff, prb + diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, rectStartColor, areaColor, 0, 180, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcr, radius, areaToColor, rectEndColor, 180, 360, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, plb - diff, plt - diff, prt + diff, prb + diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, areaColor, 0, 180);
|
||||
UGL.DrawSector(vh, pcr, radius, areaToColor, 180, 360);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var diff = Vector3.up * radius;
|
||||
if (plt.y > plb.y)
|
||||
{
|
||||
var pct = (plt + prt) / 2 - diff;
|
||||
var pcb = (plb + prb) / 2 + diff;
|
||||
if (pct.y > pcb.y)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = plt.y - plb.y;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
chart.DrawClipPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, rectEndColor, areaToColor, 270, 450, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcb, radius, rectStartColor, areaColor, 90, 270, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, areaToColor, 270, 450);
|
||||
UGL.DrawSector(vh, pcb, radius, areaColor, 90, 270);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (plt.y < plb.y)
|
||||
{
|
||||
var pct = (plt + prt) / 2 + diff;
|
||||
var pcb = (plb + prb) / 2 - diff;
|
||||
if (pct.y < pcb.y)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = plb.y - plt.y;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
chart.DrawClipPolygon(vh, prb - diff, plb - diff, plt + diff, prt + diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, rectEndColor, areaToColor, 90, 270, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcb, radius, rectStartColor, areaColor, 270, 450, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, prb - diff, plb - diff, plt + diff, prt + diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, areaToColor, 90, 270);
|
||||
UGL.DrawSector(vh, pcb, radius, areaColor, 270, 450);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBarBackground(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle,
|
||||
int colorIndex, bool highlight, float pX, float pY, float space, float barWidth, bool isYAxis, GridCoord grid)
|
||||
{
|
||||
var color = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, colorIndex, highlight, false);
|
||||
if (ChartHelper.IsClearColor(color)) return;
|
||||
if (isYAxis)
|
||||
{
|
||||
var axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
var axisWidth = axis.axisLine.GetWidth(chart.theme.axis.lineWidth);
|
||||
Vector3 plt = new Vector3(grid.context.x + axisWidth, pY + space + barWidth);
|
||||
Vector3 prt = new Vector3(grid.context.x + axisWidth + grid.context.width, pY + space + barWidth);
|
||||
Vector3 prb = new Vector3(grid.context.x + axisWidth + grid.context.width, pY + space);
|
||||
Vector3 plb = new Vector3(grid.context.x + axisWidth, pY + space);
|
||||
if (serie.barType == BarType.Capsule)
|
||||
{
|
||||
var radius = barWidth / 2;
|
||||
var diff = Vector3.right * radius;
|
||||
var pcl = (plt + plb) / 2 + diff;
|
||||
var pcr = (prt + prb) / 2 - diff;
|
||||
chart.DrawClipPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, color, color, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, color, 180, 360);
|
||||
UGL.DrawSector(vh, pcr, radius, color, 0, 180);
|
||||
if (itemStyle.NeedShowBorder())
|
||||
{
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var smoothness = chart.settings.cicleSmoothness;
|
||||
var inRadius = radius - borderWidth;
|
||||
var outRadius = radius;
|
||||
var p1 = plb + diff + Vector3.up * borderWidth / 2;
|
||||
var p2 = prb - diff + Vector3.up * borderWidth / 2;
|
||||
var p3 = plt + diff - Vector3.up * borderWidth / 2;
|
||||
var p4 = prt - diff - Vector3.up * borderWidth / 2;
|
||||
UGL.DrawLine(vh, p1, p2, borderWidth / 2, borderColor);
|
||||
UGL.DrawLine(vh, p3, p4, borderWidth / 2, borderColor);
|
||||
UGL.DrawDoughnut(vh, pcl, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
180, 360, smoothness);
|
||||
UGL.DrawDoughnut(vh, pcr, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
0, 180, smoothness);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, ref plb, ref plt, ref prt, ref prb, color, color, serie.clip, grid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
var axisWidth = axis.axisLine.GetWidth(chart.theme.axis.lineWidth);
|
||||
Vector3 plb = new Vector3(pX + space, grid.context.y + axisWidth);
|
||||
Vector3 plt = new Vector3(pX + space, grid.context.y + grid.context.height + axisWidth);
|
||||
Vector3 prt = new Vector3(pX + space + barWidth, grid.context.y + grid.context.height + axisWidth);
|
||||
Vector3 prb = new Vector3(pX + space + barWidth, grid.context.y + axisWidth);
|
||||
if (serie.barType == BarType.Capsule)
|
||||
{
|
||||
var radius = barWidth / 2;
|
||||
var diff = Vector3.up * radius;
|
||||
var pct = (plt + prt) / 2 - diff;
|
||||
var pcb = (plb + prb) / 2 + diff;
|
||||
chart.DrawClipPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, color, color,
|
||||
serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, color, 270, 450);
|
||||
UGL.DrawSector(vh, pcb, radius, color, 90, 270);
|
||||
if (itemStyle.NeedShowBorder())
|
||||
{
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var smoothness = chart.settings.cicleSmoothness;
|
||||
var inRadius = radius - borderWidth;
|
||||
var outRadius = radius;
|
||||
var p1 = plb + diff + Vector3.right * borderWidth / 2;
|
||||
var p2 = plt - diff + Vector3.right * borderWidth / 2;
|
||||
var p3 = prb + diff - Vector3.right * borderWidth / 2;
|
||||
var p4 = prt - diff - Vector3.right * borderWidth / 2;
|
||||
UGL.DrawLine(vh, p1, p2, borderWidth / 2, borderColor);
|
||||
UGL.DrawLine(vh, p3, p4, borderWidth / 2, borderColor);
|
||||
UGL.DrawDoughnut(vh, pct, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
270, 450, smoothness);
|
||||
UGL.DrawDoughnut(vh, pcb, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
90, 270, smoothness);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, color, color, serie.clip, grid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Bar/BarHandler.cs.meta
Normal file
11
Runtime/Serie/Bar/BarHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bd8425bf4c1b4bf2adf8940be58ddec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
39
Runtime/Serie/Bar/SimplifiedBar.cs
Normal file
39
Runtime/Serie/Bar/SimplifiedBar.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[Serializable]
|
||||
[SerieHandler(typeof(SimplifiedBarHandler), true)]
|
||||
[SerieConvert(typeof(SimplifiedLine), typeof(Bar))]
|
||||
[CoordOptions(typeof(GridCoord))]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[SerieExtraComponent()]
|
||||
public class SimplifiedBar : Serie, INeedSerieContainer, ISimplifiedSerie
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<SimplifiedBar>(serieName);
|
||||
serie.symbol.show = false;
|
||||
var lastValue = 0d;
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
if (i < 20)
|
||||
lastValue += UnityEngine.Random.Range(0, 5);
|
||||
else
|
||||
lastValue += UnityEngine.Random.Range(-3, 5);
|
||||
chart.AddData(serie.index, lastValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static SimplifiedBar CovertSerie(Serie serie)
|
||||
{
|
||||
var newSerie = serie.Clone<SimplifiedBar>();
|
||||
return newSerie;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Bar/SimplifiedBar.cs.meta
Normal file
11
Runtime/Serie/Bar/SimplifiedBar.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fc754e0afd4d4f138389c19611aaedb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
368
Runtime/Serie/Bar/SimplifiedBarHandler.cs
Normal file
368
Runtime/Serie/Bar/SimplifiedBarHandler.cs
Normal file
@@ -0,0 +1,368 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class SimplifiedBarHandler : SerieHandler<SimplifiedBar>
|
||||
{
|
||||
private GridCoord m_SerieGrid;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
|
||||
marker, itemFormatter, numericFormatter);
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
DrawBarSerie(vh, serie, serie.context.colorIndex);
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
|
||||
var needInteract = false;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag != needCheck)
|
||||
{
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
if (m_LegendEnter)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.context.rect.Contains(chart.pointerPos))
|
||||
{
|
||||
serie.context.pointerItemDataIndex = serieData.index;
|
||||
serie.context.pointerEnter = true;
|
||||
serieData.context.highlight = true;
|
||||
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
|
||||
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBarSerie(VertexHelper vh, SimplifiedBar serie, int colorIndex)
|
||||
{
|
||||
if (!serie.show || serie.animation.HasFadeOut())
|
||||
return;
|
||||
|
||||
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
|
||||
|
||||
Axis axis;
|
||||
Axis relativedAxis;
|
||||
|
||||
if (isY)
|
||||
{
|
||||
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
}
|
||||
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
|
||||
|
||||
if (axis == null)
|
||||
return;
|
||||
if (relativedAxis == null)
|
||||
return;
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
|
||||
if (showData.Count <= 0)
|
||||
return;
|
||||
|
||||
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
|
||||
var axisXY = isY ? m_SerieGrid.context.y : m_SerieGrid.context.x;
|
||||
|
||||
float categoryWidth = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
|
||||
float barGap = chart.GetSerieBarGap<Bar>();
|
||||
float totalBarWidth = chart.GetSerieTotalWidth<Bar>(categoryWidth, barGap);
|
||||
float barWidth = serie.GetBarWidth(categoryWidth);
|
||||
float offset = (categoryWidth - totalBarWidth) * 0.5f;
|
||||
float barGapWidth = barWidth + barWidth * barGap;
|
||||
float space = serie.barGap == -1 ? offset : offset + serie.index * barGapWidth;
|
||||
int maxCount = serie.maxShow > 0
|
||||
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
|
||||
bool dataChanging = false;
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
double yMinValue = relativedAxis.context.minValue;
|
||||
double yMaxValue = relativedAxis.context.maxValue;
|
||||
|
||||
var areaColor = ColorUtil.clearColor32;
|
||||
var areaToColor = ColorUtil.clearColor32;
|
||||
var interacting = false;
|
||||
|
||||
serie.containerIndex = m_SerieGrid.index;
|
||||
serie.containterInstanceId = m_SerieGrid.instanceId;
|
||||
serie.animation.InitProgress(axisXY, axisXY + axisLength);
|
||||
for (int i = serie.minShow; i < maxCount; i++)
|
||||
{
|
||||
var serieData = showData[i];
|
||||
if (!serieData.show || serie.IsIgnoreValue(serieData))
|
||||
{
|
||||
serie.context.dataPoints.Add(Vector3.zero);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (serieData.IsDataChanged())
|
||||
dataChanging = true;
|
||||
|
||||
var highlight = serieData.context.highlight || serie.highlight;
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
|
||||
var value = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
|
||||
var relativedValue = serieData.GetCurrData(1, dataChangeDuration, relativedAxis.inverse, yMinValue, yMaxValue);
|
||||
var borderWidth = relativedValue == 0 ? 0 : itemStyle.runtimeBorderWidth;
|
||||
|
||||
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting))
|
||||
{
|
||||
areaColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, highlight);
|
||||
areaToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, highlight);
|
||||
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
|
||||
}
|
||||
|
||||
var pX = 0f;
|
||||
var pY = 0f;
|
||||
UpdateXYPosition(m_SerieGrid, isY, axis, relativedAxis, i, categoryWidth, barWidth, value, ref pX, ref pY);
|
||||
|
||||
var barHig = AxisHelper.GetAxisValueLength(m_SerieGrid, relativedAxis, categoryWidth, relativedValue);
|
||||
var currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
|
||||
|
||||
Vector3 plb, plt, prt, prb, top;
|
||||
UpdateRectPosition(m_SerieGrid, isY, relativedValue, pX, pY, space, borderWidth, barWidth, currHig,
|
||||
out plb, out plt, out prt, out prb, out top);
|
||||
serieData.context.stackHeight = barHig;
|
||||
serieData.context.position = top;
|
||||
serieData.context.rect = Rect.MinMaxRect(plb.x, plb.y, prb.x, prt.y);
|
||||
serie.context.dataPoints.Add(top);
|
||||
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, m_SerieGrid, areaColor, areaToColor);
|
||||
|
||||
if (serie.animation.CheckDetailBreak(top, isY))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging || interacting)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateXYPosition(GridCoord grid, bool isY, Axis axis, Axis relativedAxis, int i, float categoryWidth, float barWidth,
|
||||
double value, ref float pX, ref float pY)
|
||||
{
|
||||
if (isY)
|
||||
{
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
pY = grid.context.y + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (axis.context.minMaxRange <= 0) pY = grid.context.y;
|
||||
else pY = grid.context.y + (float)((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.height - barWidth);
|
||||
}
|
||||
pX = AxisHelper.GetAxisPosition(grid, relativedAxis, categoryWidth, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
pX = grid.context.x + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (axis.context.minMaxRange <= 0) pX = grid.context.x;
|
||||
else pX = grid.context.x + (float)((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.width - barWidth);
|
||||
}
|
||||
pY = AxisHelper.GetAxisPosition(grid, relativedAxis, categoryWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRectPosition(GridCoord grid, bool isY, double yValue, float pX, float pY, float space, float borderWidth,
|
||||
float barWidth, float currHig,
|
||||
out Vector3 plb, out Vector3 plt, out Vector3 prt, out Vector3 prb, out Vector3 top)
|
||||
{
|
||||
if (isY)
|
||||
{
|
||||
if (yValue < 0)
|
||||
{
|
||||
plt = new Vector3(pX - borderWidth, pY + space + barWidth - borderWidth);
|
||||
prt = new Vector3(pX + currHig + borderWidth, pY + space + barWidth - borderWidth);
|
||||
prb = new Vector3(pX + currHig + borderWidth, pY + space + borderWidth);
|
||||
plb = new Vector3(pX - borderWidth, pY + space + borderWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
plt = new Vector3(pX + borderWidth, pY + space + barWidth - borderWidth);
|
||||
prt = new Vector3(pX + currHig - borderWidth, pY + space + barWidth - borderWidth);
|
||||
prb = new Vector3(pX + currHig - borderWidth, pY + space + borderWidth);
|
||||
plb = new Vector3(pX + borderWidth, pY + space + borderWidth);
|
||||
}
|
||||
top = new Vector3(pX + currHig - borderWidth, pY + space + barWidth / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yValue < 0)
|
||||
{
|
||||
plb = new Vector3(pX + space + borderWidth, pY - borderWidth);
|
||||
plt = new Vector3(pX + space + borderWidth, pY + currHig + borderWidth);
|
||||
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig + borderWidth);
|
||||
prb = new Vector3(pX + space + barWidth - borderWidth, pY - borderWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
|
||||
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
|
||||
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
|
||||
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
|
||||
}
|
||||
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
|
||||
}
|
||||
if (serie.clip)
|
||||
{
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
top = chart.ClampInGrid(grid, top);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, GridCoord grid, Color32 areaColor, Color32 areaToColor)
|
||||
{
|
||||
|
||||
var borderWidth = itemStyle.runtimeBorderWidth;
|
||||
if (isYAxis)
|
||||
{
|
||||
if (serie.clip)
|
||||
{
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
}
|
||||
var itemWidth = Mathf.Abs(prb.x - plt.x);
|
||||
var itemHeight = Mathf.Abs(prt.y - plb.y);
|
||||
var center = new Vector3((plt.x + prb.x) / 2, (prt.y + plb.y) / 2);
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
var invert = center.x < plb.x;
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, plb, plt, prt, prb, areaColor, areaToColor, serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
|
||||
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serie.clip)
|
||||
{
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
}
|
||||
var itemWidth = Mathf.Abs(prt.x - plb.x);
|
||||
var itemHeight = Mathf.Abs(plt.y - prb.y);
|
||||
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
var invert = center.y < plb.y;
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaToColor,
|
||||
serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
|
||||
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Bar/SimplifiedBarHandler.cs.meta
Normal file
11
Runtime/Serie/Bar/SimplifiedBarHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afd7226ecff7f4b9fad297101bc33b8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Candlestick.meta
Normal file
8
Runtime/Serie/Candlestick.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 641a5dafd45e6455ca9ef9558efe1083
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
28
Runtime/Serie/Candlestick/Candlestick.cs
Normal file
28
Runtime/Serie/Candlestick/Candlestick.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(CandlestickHandler), true)]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[SerieExtraComponent()]
|
||||
public class Candlestick : Serie, INeedSerieContainer
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Candlestick>(serieName);
|
||||
var defaultDataCount = 5;
|
||||
for (int i = 0; i < defaultDataCount; i++)
|
||||
{
|
||||
var open = Random.Range(20, 60);
|
||||
var close = Random.Range(40, 90);
|
||||
var lowest = Random.Range(0, 50);
|
||||
var heighest = Random.Range(50, 100);
|
||||
chart.AddData(serie.index, open, close, lowest, heighest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Candlestick/Candlestick.cs.meta
Normal file
11
Runtime/Serie/Candlestick/Candlestick.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1fbb6247f54f4dd2a1f3e7f6bafb8c7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
213
Runtime/Serie/Candlestick/CandlestickHandler.cs
Normal file
213
Runtime/Serie/Candlestick/CandlestickHandler.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class CandlestickHandler : SerieHandler<Candlestick>
|
||||
{
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
DrawCandlestickSerie(vh, colorIndex, serie);
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
if (dataIndex < 0)
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
title = category;
|
||||
|
||||
var color = chart.GetLegendRealShowNameColor(serie.serieName);
|
||||
var newMarker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
var newItemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
var newNumericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.category = category;
|
||||
param.dimension = 1;
|
||||
param.serieData = serieData;
|
||||
param.value = 0;
|
||||
param.total = 0;
|
||||
param.color = color;
|
||||
param.marker = newMarker;
|
||||
param.itemFormatter = newItemFormatter;
|
||||
param.numericFormatter = newNumericFormatter;
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(serie.serieName);
|
||||
param.columns.Add(string.Empty);
|
||||
|
||||
paramList.Add(param);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
param = new SerieParams();
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.dimension = i;
|
||||
param.serieData = serieData;
|
||||
param.value = serieData.GetData(i);
|
||||
param.total = SerieHelper.GetMaxData(serie, i);
|
||||
param.color = color;
|
||||
param.marker = newMarker;
|
||||
param.itemFormatter = newItemFormatter;
|
||||
param.numericFormatter = newNumericFormatter;
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(XCSettings.lang.GetCandlestickDimensionName(i));
|
||||
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCandlestickSerie(VertexHelper vh, int colorIndex, Candlestick serie)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
XAxis xAxis;
|
||||
YAxis yAxis;
|
||||
GridCoord grid;
|
||||
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
|
||||
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
|
||||
if (!chart.TryGetChartComponent<GridCoord>(out grid, xAxis.gridIndex)) return;
|
||||
var theme = chart.theme;
|
||||
var dataZoom = chart.GetDataZoomOfAxis(xAxis);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, showData.Count, dataZoom);
|
||||
float barWidth = serie.GetBarWidth(categoryWidth);
|
||||
float space = (categoryWidth - barWidth) / 2;
|
||||
int maxCount = serie.maxShow > 0
|
||||
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
|
||||
bool dataChanging = false;
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
double yMinValue = yAxis.context.minValue;
|
||||
double yMaxValue = yAxis.context.maxValue;
|
||||
var isYAxis = false;
|
||||
serie.containerIndex = grid.index;
|
||||
serie.containterInstanceId = grid.instanceId;
|
||||
for (int i = serie.minShow; i < maxCount; i++)
|
||||
{
|
||||
var serieData = showData[i];
|
||||
if (serie.IsIgnoreValue(serieData))
|
||||
{
|
||||
serie.context.dataPoints.Add(Vector3.zero);
|
||||
continue;
|
||||
}
|
||||
var highlight = serie.data[i].context.highlight || serie.highlight;
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
|
||||
var open = serieData.GetCurrData(0, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var close = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var lowest = serieData.GetCurrData(2, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var heighest = serieData.GetCurrData(3, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var isRise = yAxis.inverse ? close < open : close > open;
|
||||
var borderWidth = open == 0 ? 0f
|
||||
: (itemStyle.runtimeBorderWidth == 0 ? theme.serie.candlestickBorderWidth
|
||||
: itemStyle.runtimeBorderWidth);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
float pX = grid.context.x + i * categoryWidth;
|
||||
float zeroY = grid.context.y + yAxis.context.offset;
|
||||
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
|
||||
float pY = zeroY;
|
||||
var barHig = 0f;
|
||||
double valueTotal = yMaxValue - yMinValue;
|
||||
var minCut = (yMinValue > 0 ? yMinValue : 0);
|
||||
if (valueTotal != 0)
|
||||
{
|
||||
barHig = (float)((close - open) / valueTotal * grid.context.height);
|
||||
pY += (float)((open - minCut) / valueTotal * grid.context.height);
|
||||
}
|
||||
serieData.context.stackHeight = barHig;
|
||||
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
|
||||
Vector3 plb, plt, prt, prb, top;
|
||||
|
||||
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
|
||||
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
|
||||
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
|
||||
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
|
||||
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
|
||||
if (serie.clip)
|
||||
{
|
||||
plb = chart.ClampInGrid(grid, plb);
|
||||
plt = chart.ClampInGrid(grid, plt);
|
||||
prt = chart.ClampInGrid(grid, prt);
|
||||
prb = chart.ClampInGrid(grid, prb);
|
||||
top = chart.ClampInGrid(grid, top);
|
||||
}
|
||||
serie.context.dataPoints.Add(top);
|
||||
var areaColor = isRise
|
||||
? itemStyle.GetColor(theme.serie.candlestickColor)
|
||||
: itemStyle.GetColor0(theme.serie.candlestickColor0);
|
||||
var borderColor = isRise
|
||||
? itemStyle.GetBorderColor(theme.serie.candlestickBorderColor)
|
||||
: itemStyle.GetBorderColor0(theme.serie.candlestickBorderColor0);
|
||||
var itemWidth = Mathf.Abs(prt.x - plb.x);
|
||||
var itemHeight = Mathf.Abs(plt.y - prb.y);
|
||||
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
|
||||
var lowPos = new Vector3(center.x, zeroY + (float)((lowest - minCut) / valueTotal * grid.context.height));
|
||||
var heighPos = new Vector3(center.x, zeroY + (float)((heighest - minCut) / valueTotal * grid.context.height));
|
||||
var openCenterPos = new Vector3(center.x, prb.y);
|
||||
var closeCenterPos = new Vector3(center.x, prt.y);
|
||||
if (barWidth > 2f * borderWidth)
|
||||
{
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
|
||||
serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
|
||||
}
|
||||
if (isRise)
|
||||
{
|
||||
UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
|
||||
UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
|
||||
UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Candlestick/CandlestickHandler.cs.meta
Normal file
11
Runtime/Serie/Candlestick/CandlestickHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d530c536c5784f2593e9a7c5a57df16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Runtime/Serie/Candlestick/SimplifiedCandlestick.cs
Normal file
37
Runtime/Serie/Candlestick/SimplifiedCandlestick.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(SimplifiedCandlestickHandler), true)]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[SerieExtraComponent()]
|
||||
public class SimplifiedCandlestick : Serie, INeedSerieContainer, ISimplifiedSerie
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<SimplifiedCandlestick>(serieName);
|
||||
|
||||
var lastValue = 50d;
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
lastValue += UnityEngine.Random.Range(-10, 20);
|
||||
var open = lastValue + Random.Range(-10, 5);
|
||||
var close = lastValue + Random.Range(-5, 10);
|
||||
var lowest = lastValue + Random.Range(-15, -10);
|
||||
var heighest = lastValue + Random.Range(10, 20);
|
||||
chart.AddData(serie.index, open, close, lowest, heighest);
|
||||
}
|
||||
}
|
||||
|
||||
public static SimplifiedCandlestick CovertSerie(Serie serie)
|
||||
{
|
||||
var newSerie = serie.Clone<SimplifiedCandlestick>();
|
||||
return newSerie;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Candlestick/SimplifiedCandlestick.cs.meta
Normal file
11
Runtime/Serie/Candlestick/SimplifiedCandlestick.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1202f0da64c484488bb69b8382af9918
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
214
Runtime/Serie/Candlestick/SimplifiedCandlestickHandler.cs
Normal file
214
Runtime/Serie/Candlestick/SimplifiedCandlestickHandler.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class SimplifiedCandlestickHandler : SerieHandler<SimplifiedCandlestick>
|
||||
{
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
DrawCandlestickSerie(vh, colorIndex, serie);
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
if (dataIndex < 0)
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
title = category;
|
||||
|
||||
var color = chart.GetLegendRealShowNameColor(serie.serieName);
|
||||
var newMarker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
var newItemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
var newNumericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.category = category;
|
||||
param.dimension = 1;
|
||||
param.serieData = serieData;
|
||||
param.value = 0;
|
||||
param.total = 0;
|
||||
param.color = color;
|
||||
param.marker = newMarker;
|
||||
param.itemFormatter = newItemFormatter;
|
||||
param.numericFormatter = newNumericFormatter;
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(serie.serieName);
|
||||
param.columns.Add(string.Empty);
|
||||
|
||||
paramList.Add(param);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
param = new SerieParams();
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.dimension = i;
|
||||
param.serieData = serieData;
|
||||
param.value = serieData.GetData(i);
|
||||
param.total = SerieHelper.GetMaxData(serie, i);
|
||||
param.color = color;
|
||||
param.marker = newMarker;
|
||||
param.itemFormatter = newItemFormatter;
|
||||
param.numericFormatter = newNumericFormatter;
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(XCSettings.lang.GetCandlestickDimensionName(i));
|
||||
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCandlestickSerie(VertexHelper vh, int colorIndex, SimplifiedCandlestick serie)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
XAxis xAxis;
|
||||
YAxis yAxis;
|
||||
GridCoord grid;
|
||||
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
|
||||
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
|
||||
if (!chart.TryGetChartComponent<GridCoord>(out grid, xAxis.gridIndex)) return;
|
||||
var theme = chart.theme;
|
||||
var dataZoom = chart.GetDataZoomOfAxis(xAxis);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, showData.Count, dataZoom);
|
||||
float barWidth = serie.GetBarWidth(categoryWidth);
|
||||
float space = (categoryWidth - barWidth) / 2;
|
||||
int maxCount = serie.maxShow > 0
|
||||
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
|
||||
bool dataChanging = false;
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
double yMinValue = yAxis.context.minValue;
|
||||
double yMaxValue = yAxis.context.maxValue;
|
||||
var isYAxis = false;
|
||||
var itemStyle = serie.itemStyle;
|
||||
serie.containerIndex = grid.index;
|
||||
serie.containterInstanceId = grid.instanceId;
|
||||
|
||||
for (int i = serie.minShow; i < maxCount; i++)
|
||||
{
|
||||
var serieData = showData[i];
|
||||
if (serie.IsIgnoreValue(serieData))
|
||||
{
|
||||
serie.context.dataPoints.Add(Vector3.zero);
|
||||
continue;
|
||||
}
|
||||
var open = serieData.GetCurrData(0, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var close = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var lowest = serieData.GetCurrData(2, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var heighest = serieData.GetCurrData(3, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
var isRise = yAxis.inverse ? close < open : close > open;
|
||||
var borderWidth = open == 0 ? 0f
|
||||
: (itemStyle.runtimeBorderWidth == 0 ? theme.serie.candlestickBorderWidth
|
||||
: itemStyle.runtimeBorderWidth);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
float pX = grid.context.x + i * categoryWidth;
|
||||
float zeroY = grid.context.y + yAxis.context.offset;
|
||||
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
|
||||
float pY = zeroY;
|
||||
var barHig = 0f;
|
||||
double valueTotal = yMaxValue - yMinValue;
|
||||
var minCut = (yMinValue > 0 ? yMinValue : 0);
|
||||
if (valueTotal != 0)
|
||||
{
|
||||
barHig = (float)((close - open) / valueTotal * grid.context.height);
|
||||
pY += (float)((open - minCut) / valueTotal * grid.context.height);
|
||||
}
|
||||
serieData.context.stackHeight = barHig;
|
||||
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
|
||||
Vector3 plb, plt, prt, prb, top;
|
||||
|
||||
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
|
||||
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
|
||||
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
|
||||
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
|
||||
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
|
||||
// if (serie.clip)
|
||||
// {
|
||||
// plb = chart.ClampInGrid(grid, plb);
|
||||
// plt = chart.ClampInGrid(grid, plt);
|
||||
// prt = chart.ClampInGrid(grid, prt);
|
||||
// prb = chart.ClampInGrid(grid, prb);
|
||||
// top = chart.ClampInGrid(grid, top);
|
||||
// }
|
||||
serie.context.dataPoints.Add(top);
|
||||
var areaColor = isRise
|
||||
? itemStyle.GetColor(theme.serie.candlestickColor)
|
||||
: itemStyle.GetColor0(theme.serie.candlestickColor0);
|
||||
var borderColor = isRise
|
||||
? itemStyle.GetBorderColor(theme.serie.candlestickBorderColor)
|
||||
: itemStyle.GetBorderColor0(theme.serie.candlestickBorderColor0);
|
||||
var itemWidth = Mathf.Abs(prt.x - plb.x);
|
||||
var itemHeight = Mathf.Abs(plt.y - prb.y);
|
||||
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
|
||||
var lowPos = new Vector3(center.x, zeroY + (float)((lowest - minCut) / valueTotal * grid.context.height));
|
||||
var heighPos = new Vector3(center.x, zeroY + (float)((heighest - minCut) / valueTotal * grid.context.height));
|
||||
var openCenterPos = new Vector3(center.x, prb.y);
|
||||
var closeCenterPos = new Vector3(center.x, prt.y);
|
||||
if (barWidth > 2f * borderWidth)
|
||||
{
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
|
||||
serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis, 0.5f);
|
||||
}
|
||||
if (isRise)
|
||||
{
|
||||
UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
|
||||
UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
|
||||
UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
|
||||
}
|
||||
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42727a035319b4eab92ddf0742630115
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Heatmap.meta
Normal file
8
Runtime/Serie/Heatmap.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70535a50c140c47cc8cac1820dc03170
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
28
Runtime/Serie/Heatmap/Heatmap.cs
Normal file
28
Runtime/Serie/Heatmap/Heatmap.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(HeatmapHandler), true)]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(Emphasis))]
|
||||
public class Heatmap : Serie, INeedSerieContainer
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Heatmap>(serieName);
|
||||
serie.itemStyle.show = true;
|
||||
serie.itemStyle.borderWidth = 1;
|
||||
serie.itemStyle.borderColor = Color.clear;
|
||||
|
||||
var emphasis = serie.AddExtraComponent<Emphasis>();
|
||||
emphasis.show = true;
|
||||
emphasis.itemStyle.show = true;
|
||||
emphasis.itemStyle.borderWidth = 1;
|
||||
emphasis.itemStyle.borderColor = Color.black;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Heatmap/Heatmap.cs.meta
Normal file
11
Runtime/Serie/Heatmap/Heatmap.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a9984972d3c74a01945c4064739a826
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
189
Runtime/Serie/Heatmap/HeatmapHandler.cs
Normal file
189
Runtime/Serie/Heatmap/HeatmapHandler.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class HeatmapHandler : SerieHandler<Heatmap>
|
||||
{
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
DrawHeatmapSerie(vh, colorIndex, serie);
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
title = serie.serieName;
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.dimension = 2;
|
||||
param.serieData = serieData;
|
||||
param.color = chart.theme.GetColor(serie.index);
|
||||
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(category);
|
||||
param.columns.Add(ChartCached.NumberToStr(serieData.GetData(2), param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
|
||||
if (!chart.isPointerInChart)
|
||||
return;
|
||||
|
||||
var grid = chart.GetChartComponent<GridCoord>(serie.containerIndex);
|
||||
if (grid == null)
|
||||
return;
|
||||
|
||||
if (!grid.IsPointerEnter())
|
||||
return;
|
||||
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.context.rect.Contains(chart.pointerPos))
|
||||
{
|
||||
serie.context.pointerItemDataIndex = serieData.index;
|
||||
serie.context.pointerEnter = true;
|
||||
serieData.context.highlight = true;
|
||||
chart.RefreshTopPainter();
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHeatmapSerie(VertexHelper vh, int colorIndex, Heatmap serie)
|
||||
{
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
XAxis xAxis;
|
||||
YAxis yAxis;
|
||||
GridCoord grid;
|
||||
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
|
||||
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
|
||||
if (!chart.TryGetChartComponent<GridCoord>(out grid, xAxis.gridIndex)) return;
|
||||
xAxis.boundaryGap = true;
|
||||
yAxis.boundaryGap = true;
|
||||
var visualMap = chart.GetVisualMapOfSerie(serie);
|
||||
var emphasis = serie.emphasis;
|
||||
var xCount = xAxis.data.Count;
|
||||
var yCount = yAxis.data.Count;
|
||||
var xWidth = grid.context.width / xCount;
|
||||
var yWidth = grid.context.height / yCount;
|
||||
|
||||
var zeroX = grid.context.x;
|
||||
var zeroY = grid.context.y;
|
||||
var dataList = serie.GetDataList();
|
||||
var rangeMin = visualMap.rangeMin;
|
||||
var rangeMax = visualMap.rangeMax;
|
||||
var color = chart.theme.GetColor(serie.index);
|
||||
var borderWidth = serie.itemStyle.show ? serie.itemStyle.borderWidth : 0;
|
||||
var rectWid = xWidth - 2 * borderWidth;
|
||||
var rectHig = yWidth - 2 * borderWidth;
|
||||
var borderColor = serie.itemStyle.opacity > 0 ? serie.itemStyle.borderColor : ChartConst.clearColor32;
|
||||
borderColor.a = (byte)(borderColor.a * serie.itemStyle.opacity);
|
||||
var borderToColor = serie.itemStyle.opacity > 0 ? serie.itemStyle.borderToColor : ChartConst.clearColor32;
|
||||
borderToColor.a = (byte)(borderToColor.a * serie.itemStyle.opacity);
|
||||
serie.context.dataPoints.Clear();
|
||||
serie.animation.InitProgress(0, xCount);
|
||||
var animationIndex = serie.animation.GetCurrIndex();
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var dataChanging = false;
|
||||
serie.containerIndex = grid.index;
|
||||
serie.containterInstanceId = grid.instanceId;
|
||||
for (int i = 0; i < xCount; i++)
|
||||
{
|
||||
for (int j = 0; j < yCount; j++)
|
||||
{
|
||||
var dataIndex = i * yCount + j;
|
||||
if (dataIndex >= dataList.Count) continue;
|
||||
var serieData = dataList[dataIndex];
|
||||
var dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count);
|
||||
serieData.index = dataIndex;
|
||||
if (serie.IsIgnoreIndex(dataIndex, dimension))
|
||||
{
|
||||
serie.context.dataPoints.Add(Vector3.zero);
|
||||
continue;
|
||||
}
|
||||
var value = serieData.GetCurrData(dimension, dataChangeDuration, yAxis.inverse,
|
||||
yAxis.context.minValue, yAxis.context.maxValue);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
var pos = new Vector3(zeroX + (i + (xAxis.boundaryGap ? 0.5f : 0)) * xWidth,
|
||||
zeroY + (j + (yAxis.boundaryGap ? 0.5f : 0)) * yWidth);
|
||||
serie.context.dataPoints.Add(pos);
|
||||
serieData.context.canShowLabel = false;
|
||||
serieData.context.rect = new Rect(pos.x - rectWid / 2, pos.y - rectHig / 2, rectWid, rectHig);
|
||||
if (value == 0) continue;
|
||||
if ((value < rangeMin && rangeMin != visualMap.min)
|
||||
|| (value > rangeMax && rangeMax != visualMap.max))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!visualMap.IsInSelectedValue(value)) continue;
|
||||
color = visualMap.GetColor(value);
|
||||
if (animationIndex >= 0 && i > animationIndex) continue;
|
||||
serieData.context.canShowLabel = true;
|
||||
var highlight = (serieData.context.highlight)
|
||||
|| visualMap.context.pointerIndex > 0;
|
||||
|
||||
UGL.DrawRectangle(vh, pos, rectWid / 2, rectHig / 2, color);
|
||||
if (borderWidth > 0 && !ChartHelper.IsClearColor(borderColor))
|
||||
{
|
||||
UGL.DrawBorder(vh, pos, rectWid, rectHig, borderWidth, borderColor, borderToColor);
|
||||
}
|
||||
if (visualMap.hoverLink && highlight && emphasis != null && emphasis.show
|
||||
&& emphasis.itemStyle.borderWidth > 0)
|
||||
{
|
||||
var emphasisBorderWidth = emphasis.itemStyle.borderWidth;
|
||||
var emphasisBorderColor = emphasis.itemStyle.opacity > 0
|
||||
? emphasis.itemStyle.borderColor : ChartConst.clearColor32;
|
||||
var emphasisBorderToColor = emphasis.itemStyle.opacity > 0
|
||||
? emphasis.itemStyle.borderToColor : ChartConst.clearColor32;
|
||||
UGL.DrawBorder(vh, pos, rectWid, rectHig, emphasisBorderWidth, emphasisBorderColor,
|
||||
emphasisBorderToColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(xCount);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Heatmap/HeatmapHandler.cs.meta
Normal file
11
Runtime/Serie/Heatmap/HeatmapHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a5cd70274da44d50b48fc04d8b52e21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
185
Runtime/Serie/InteractData.cs
Normal file
185
Runtime/Serie/InteractData.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class InteractData
|
||||
{
|
||||
private float m_PreviousValue = 0;
|
||||
private float m_TargetValue = 0;
|
||||
private Color32 m_PreviousColor;
|
||||
private Color32 m_TargetColor;
|
||||
private Color32 m_PreviousToColor;
|
||||
private Color32 m_TargetToColor;
|
||||
private float m_UpdateTime = 0;
|
||||
private bool m_UpdateFlag = false;
|
||||
private bool m_ValueEnable = false;
|
||||
|
||||
public void SetValue(ref bool needInteract, float size, bool highlight, float rate = 1.3f)
|
||||
{
|
||||
size = highlight ? size * rate : size;
|
||||
SetValue(ref needInteract, size);
|
||||
}
|
||||
|
||||
public void SetValue(ref bool needInteract, float size)
|
||||
{
|
||||
if (m_TargetValue != size)
|
||||
{
|
||||
needInteract = true;
|
||||
m_UpdateFlag = true;
|
||||
m_ValueEnable = true;
|
||||
m_UpdateTime = Time.time;
|
||||
m_PreviousValue = m_TargetValue;
|
||||
m_TargetValue = size;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetColor(ref bool needInteract, Color32 color)
|
||||
{
|
||||
if (!ChartHelper.IsValueEqualsColor(color, m_TargetColor))
|
||||
{
|
||||
needInteract = true;
|
||||
m_UpdateFlag = true;
|
||||
m_ValueEnable = true;
|
||||
m_UpdateTime = Time.time;
|
||||
m_PreviousColor = m_TargetColor;
|
||||
m_TargetColor = color;
|
||||
}
|
||||
}
|
||||
public void SetColor(ref bool needInteract, Color32 color, Color32 toColor)
|
||||
{
|
||||
SetColor(ref needInteract, color);
|
||||
if (!ChartHelper.IsValueEqualsColor(toColor, m_TargetToColor))
|
||||
{
|
||||
needInteract = true;
|
||||
m_UpdateFlag = true;
|
||||
m_ValueEnable = true;
|
||||
m_UpdateTime = Time.time;
|
||||
m_PreviousToColor = m_TargetToColor;
|
||||
m_TargetToColor = toColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValueAndColor(ref bool needInteract, float value, Color32 color)
|
||||
{
|
||||
SetValue(ref needInteract, value);
|
||||
SetColor(ref needInteract, color);
|
||||
}
|
||||
|
||||
public void SetValueAndColor(ref bool needInteract, float value, Color32 color, Color32 toColor)
|
||||
{
|
||||
SetValue(ref needInteract, value);
|
||||
SetColor(ref needInteract, color, toColor);
|
||||
}
|
||||
|
||||
public bool TryGetValue(ref float value, ref bool interacting, float animationDuration = 250)
|
||||
{
|
||||
if (!m_ValueEnable || m_PreviousValue == 0)
|
||||
return false;
|
||||
if (m_UpdateFlag)
|
||||
{
|
||||
var time = Time.time - m_UpdateTime;
|
||||
var total = animationDuration / 1000;
|
||||
var rate = time / total;
|
||||
if (rate > 1) rate = 1;
|
||||
if (rate < 1)
|
||||
{
|
||||
interacting = true;
|
||||
value = Mathf.Lerp(m_PreviousValue, m_TargetValue, rate);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UpdateFlag = false;
|
||||
}
|
||||
}
|
||||
value = m_TargetValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetColor(ref Color32 color, ref bool interacting, float animationDuration = 250)
|
||||
{
|
||||
if (!m_ValueEnable)
|
||||
return false;
|
||||
if (m_UpdateFlag)
|
||||
{
|
||||
var time = Time.time - m_UpdateTime;
|
||||
var total = animationDuration / 1000;
|
||||
var rate = time / total;
|
||||
if (rate > 1) rate = 1;
|
||||
if (rate < 1)
|
||||
{
|
||||
interacting = true;
|
||||
color = Color32.Lerp(m_PreviousColor, m_TargetColor, rate);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UpdateFlag = false;
|
||||
}
|
||||
}
|
||||
color = m_TargetColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetColor(ref Color32 color, ref Color32 toColor, ref bool interacting, float animationDuration = 250)
|
||||
{
|
||||
if (!m_ValueEnable)
|
||||
return false;
|
||||
if (m_UpdateFlag)
|
||||
{
|
||||
var time = Time.time - m_UpdateTime;
|
||||
var total = animationDuration / 1000;
|
||||
var rate = time / total;
|
||||
if (rate > 1) rate = 1;
|
||||
if (rate < 1)
|
||||
{
|
||||
interacting = true;
|
||||
color = Color32.Lerp(m_PreviousColor, m_TargetColor, rate);
|
||||
toColor = Color32.Lerp(m_PreviousToColor, m_TargetToColor, rate);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UpdateFlag = false;
|
||||
}
|
||||
}
|
||||
color = m_TargetColor;
|
||||
toColor = m_TargetToColor;
|
||||
return true;
|
||||
}
|
||||
public bool TryGetValueAndColor(ref float value, ref Color32 color, ref Color32 toColor, ref bool interacting, float animationDuration = 250)
|
||||
{
|
||||
if (!m_ValueEnable)
|
||||
return false;
|
||||
if (m_UpdateFlag)
|
||||
{
|
||||
var time = Time.time - m_UpdateTime;
|
||||
var total = animationDuration / 1000;
|
||||
var rate = time / total;
|
||||
if (rate > 1) rate = 1;
|
||||
if (rate < 1)
|
||||
{
|
||||
interacting = true;
|
||||
value = Mathf.Lerp(m_PreviousValue, m_TargetValue, rate);
|
||||
color = Color32.Lerp(m_PreviousColor, m_TargetColor, rate);
|
||||
toColor = Color32.Lerp(m_PreviousToColor, m_TargetToColor, rate);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UpdateFlag = false;
|
||||
}
|
||||
}
|
||||
value = m_TargetValue;
|
||||
color = m_TargetColor;
|
||||
toColor = m_TargetToColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
m_ValueEnable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/InteractData.cs.meta
Normal file
11
Runtime/Serie/InteractData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ab01b44ab2454ef7ac2d71313c3d707
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Line.meta
Normal file
8
Runtime/Serie/Line.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61f1a04d9920849e7861bebdfd070384
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
39
Runtime/Serie/Line/Line.cs
Normal file
39
Runtime/Serie/Line/Line.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[Serializable]
|
||||
[SerieHandler(typeof(LineHandler), true)]
|
||||
[SerieConvert(typeof(Bar), typeof(Pie))]
|
||||
[CoordOptions(typeof(GridCoord), typeof(PolarCoord))]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[SerieExtraComponent(
|
||||
typeof(LabelStyle),
|
||||
typeof(EndLabelStyle),
|
||||
typeof(LineArrow),
|
||||
typeof(AreaStyle),
|
||||
typeof(IconStyle),
|
||||
typeof(Emphasis))]
|
||||
public class Line : Serie, INeedSerieContainer
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Line>(serieName);
|
||||
serie.symbol.show = true;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
chart.AddData(serie.index, UnityEngine.Random.Range(10, 90));
|
||||
}
|
||||
}
|
||||
|
||||
public static Line CovertSerie(Serie serie)
|
||||
{
|
||||
var newSerie = serie.Clone<Line>();
|
||||
return newSerie;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Line/Line.cs.meta
Normal file
11
Runtime/Serie/Line/Line.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 883eff3dc77e0439a80d257577790cbc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
447
Runtime/Serie/Line/LineHandler.GridCoord.cs
Normal file
447
Runtime/Serie/Line/LineHandler.GridCoord.cs
Normal file
@@ -0,0 +1,447 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
/// <summary>
|
||||
/// For grid coord
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed partial class LineHandler : SerieHandler<Line>
|
||||
{
|
||||
List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
|
||||
private GridCoord m_SerieGrid;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
|
||||
marker, itemFormatter, numericFormatter);
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
if (serie.IsUseCoord<PolarCoord>())
|
||||
{
|
||||
DrawPolarLine(vh, serie);
|
||||
DrawPolarLineSymbol(vh);
|
||||
}
|
||||
else if (serie.IsUseCoord<GridCoord>())
|
||||
{
|
||||
DrawLineSerie(vh, serie);
|
||||
|
||||
if (!SeriesHelper.IsStack(chart.series))
|
||||
{
|
||||
DrawLinePoint(vh, serie);
|
||||
DrawLineArrow(vh, serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawTop(VertexHelper vh)
|
||||
{
|
||||
if (serie.IsUseCoord<GridCoord>())
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
{
|
||||
DrawLinePoint(vh, serie);
|
||||
DrawLineArrow(vh, serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
|
||||
var lineWidth = 0f;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag != needCheck)
|
||||
{
|
||||
var needAnimation1 = false;
|
||||
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
serie.interact.SetValue(ref needAnimation1, lineWidth, false);
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needAnimation1, symbolSize);
|
||||
}
|
||||
if (needAnimation1)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
|
||||
var themeSymbolSelectedSize = chart.theme.serie.lineSymbolSelectedSize;
|
||||
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
|
||||
var needInteract = false;
|
||||
if (m_LegendEnter)
|
||||
{
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
}
|
||||
else if (serie.context.isTriggerByAxis)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
|
||||
if (i == serie.context.pointerItemDataIndex)
|
||||
{
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var dist = Vector3.Distance(chart.pointerPos, serieData.context.position);
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
|
||||
if (dist <= symbolSelectedSize)
|
||||
{
|
||||
serie.context.pointerItemDataIndex = serieData.index;
|
||||
serie.context.pointerEnter = true;
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true);
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLinePoint(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (!serie.show || serie.IsPerformanceMode())
|
||||
return;
|
||||
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var count = serie.context.dataPoints.Count;
|
||||
var clip = SeriesHelper.IsAnyClipSerie(chart.series);
|
||||
var theme = chart.theme;
|
||||
var interacting = false;
|
||||
var lineArrow = serie.lineArrow;
|
||||
//var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var serieData = serie.GetSerieData(i);
|
||||
if (serieData == null)
|
||||
continue;
|
||||
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
|
||||
if (!symbol.show || !symbol.ShowSymbol(i, count))
|
||||
continue;
|
||||
|
||||
var pos = serie.context.dataPoints[i];
|
||||
// if (serie.animation.CheckDetailBreak(pos, isY))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
if (lineArrow != null && lineArrow.show)
|
||||
{
|
||||
if (lineArrow.position == LineArrow.Position.Start && i == 0)
|
||||
continue;
|
||||
if (lineArrow.position == LineArrow.Position.End && i == count - 1)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ChartHelper.IsIngore(pos))
|
||||
continue;
|
||||
|
||||
var highlight = serie.data[i].context.highlight || serie.highlight;
|
||||
var symbolSize = highlight
|
||||
? theme.serie.lineSymbolSelectedSize
|
||||
: theme.serie.lineSymbolSize;
|
||||
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
|
||||
{
|
||||
symbolSize = highlight
|
||||
? symbol.GetSelectedSize(serieData.data, symbolSize)
|
||||
: symbol.GetSize(serieData.data, symbolSize);
|
||||
serieData.interact.SetValue(ref interacting, symbolSize);
|
||||
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
|
||||
}
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, theme, serie.index, highlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, theme, serie.index, highlight);
|
||||
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, theme, serie.index, highlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, theme, highlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
|
||||
|
||||
chart.DrawClipSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
|
||||
symbolColor, symbolToColor, symbolEmptyColor, symbol.gap, clip, cornerRadius, m_SerieGrid,
|
||||
i > 0 ? serie.context.dataPoints[i - 1] : m_SerieGrid.context.position);
|
||||
}
|
||||
if (interacting)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLineArrow(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (!serie.show || serie.lineArrow == null || !serie.lineArrow.show)
|
||||
return;
|
||||
|
||||
if (serie.context.dataPoints.Count < 2)
|
||||
return;
|
||||
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serie.index, false);
|
||||
var startPos = Vector3.zero;
|
||||
var arrowPos = Vector3.zero;
|
||||
var lineArrow = serie.lineArrow.arrow;
|
||||
var dataPoints = serie.context.drawPoints;
|
||||
switch (serie.lineArrow.position)
|
||||
{
|
||||
case LineArrow.Position.End:
|
||||
if (dataPoints.Count < 3)
|
||||
{
|
||||
startPos = dataPoints[dataPoints.Count - 2].position;
|
||||
arrowPos = dataPoints[dataPoints.Count - 1].position;
|
||||
}
|
||||
else
|
||||
{
|
||||
startPos = dataPoints[dataPoints.Count - 3].position;
|
||||
arrowPos = dataPoints[dataPoints.Count - 2].position;
|
||||
}
|
||||
UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
|
||||
lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
|
||||
|
||||
break;
|
||||
|
||||
case LineArrow.Position.Start:
|
||||
startPos = dataPoints[1].position;
|
||||
arrowPos = dataPoints[0].position;
|
||||
UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
|
||||
lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLineSerie(VertexHelper vh, Line serie)
|
||||
{
|
||||
if (!serie.show)
|
||||
return;
|
||||
if (serie.animation.HasFadeOut())
|
||||
return;
|
||||
|
||||
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
|
||||
|
||||
Axis axis;
|
||||
Axis relativedAxis;
|
||||
|
||||
if (isY)
|
||||
{
|
||||
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
}
|
||||
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
|
||||
|
||||
if (axis == null)
|
||||
return;
|
||||
if (relativedAxis == null)
|
||||
return;
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var visualMap = chart.GetVisualMapOfSerie(serie);
|
||||
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
|
||||
if (showData.Count <= 0)
|
||||
return;
|
||||
|
||||
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
|
||||
var scaleWid = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
|
||||
|
||||
int maxCount = serie.maxShow > 0
|
||||
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
int rate = LineHelper.GetDataAverageRate(serie, m_SerieGrid, maxCount, false);
|
||||
var totalAverage = serie.sampleAverage > 0
|
||||
? serie.sampleAverage
|
||||
: DataHelper.DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
|
||||
var dataChanging = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
|
||||
var interacting = false;
|
||||
var lineWidth = LineHelper.GetLineWidth(ref interacting, serie, chart.theme.serie.lineWidth);
|
||||
|
||||
axis.context.scaleWidth = scaleWid;
|
||||
serie.containerIndex = m_SerieGrid.index;
|
||||
serie.containterInstanceId = m_SerieGrid.instanceId;
|
||||
|
||||
Serie lastSerie = null;
|
||||
var isStack = SeriesHelper.IsStack<Line>(chart.series, serie.stack);
|
||||
if (isStack)
|
||||
{
|
||||
lastSerie = SeriesHelper.GetLastStackSerie(chart.series, serie);
|
||||
SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
|
||||
}
|
||||
|
||||
for (int i = serie.minShow; i < maxCount; i += rate)
|
||||
{
|
||||
var serieData = showData[i];
|
||||
var isIgnore = serie.IsIgnoreValue(serieData);
|
||||
if (isIgnore)
|
||||
{
|
||||
serieData.context.stackHeight = 0;
|
||||
serieData.context.position = Vector3.zero;
|
||||
if (serie.ignoreLineBreak && serie.context.dataIgnores.Count > 0)
|
||||
{
|
||||
serie.context.dataIgnores[serie.context.dataIgnores.Count - 1] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var np = Vector3.zero;
|
||||
var xValue = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
|
||||
var relativedValue = DataHelper.SampleValue(ref showData, serie.sampleType, rate, serie.minShow,
|
||||
maxCount, totalAverage, i, dataChangeDuration, ref dataChanging, relativedAxis);
|
||||
|
||||
serieData.context.stackHeight = GetDataPoint(isY, axis, relativedAxis, m_SerieGrid, xValue, relativedValue,
|
||||
i, scaleWid, isStack, ref np);
|
||||
|
||||
serieData.context.position = np;
|
||||
|
||||
serie.context.dataPoints.Add(np);
|
||||
serie.context.dataIgnores.Add(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataChanging || interacting)
|
||||
chart.RefreshPainter(serie);
|
||||
|
||||
if (serie.context.dataPoints.Count <= 0)
|
||||
return;
|
||||
|
||||
serie.animation.InitProgress(serie.context.dataPoints, isY);
|
||||
|
||||
VisualMapHelper.AutoSetLineMinMax(visualMap, serie, isY, axis, relativedAxis);
|
||||
LineHelper.UpdateSerieDrawPoints(serie, chart.settings, chart.theme, lineWidth, isY);
|
||||
LineHelper.DrawSerieLineArea(vh, serie, lastSerie, chart.theme, isY, axis, relativedAxis, m_SerieGrid);
|
||||
LineHelper.DrawSerieLine(vh, chart.theme, serie, visualMap, m_SerieGrid, axis, relativedAxis, lineWidth);
|
||||
|
||||
serie.context.vertCount = vh.currentVertCount;
|
||||
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private float GetDataPoint(bool isY, Axis axis, Axis relativedAxis, GridCoord grid, double xValue,
|
||||
double yValue, int i, float scaleWid, bool isStack, ref Vector3 np)
|
||||
{
|
||||
float xPos, yPos;
|
||||
var gridXY = isY ? grid.context.x : grid.context.y;
|
||||
|
||||
if (isY)
|
||||
{
|
||||
var valueHig = AxisHelper.GetAxisValueLength(grid, relativedAxis, scaleWid, yValue);
|
||||
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
|
||||
|
||||
xPos = gridXY + valueHig;
|
||||
yPos = AxisHelper.GetAxisPosition(grid, axis, scaleWid, xValue);
|
||||
|
||||
if (isStack)
|
||||
{
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
xPos += m_StackSerieData[n][i].context.stackHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var valueHig = AxisHelper.GetAxisValueLength(grid, relativedAxis, scaleWid, yValue);
|
||||
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
|
||||
|
||||
yPos = gridXY + valueHig;
|
||||
xPos = AxisHelper.GetAxisPosition(grid, axis, scaleWid, xValue);
|
||||
|
||||
if (isStack)
|
||||
{
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
yPos += m_StackSerieData[n][i].context.stackHeight;
|
||||
}
|
||||
}
|
||||
np = new Vector3(xPos, yPos);
|
||||
return yPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Line/LineHandler.GridCoord.cs.meta
Normal file
11
Runtime/Serie/Line/LineHandler.GridCoord.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34168c2605d4546c291adeb8e857fd62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
127
Runtime/Serie/Line/LineHandler.PolarCoord.cs
Normal file
127
Runtime/Serie/Line/LineHandler.PolarCoord.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
/// <summary>
|
||||
/// For polar coord
|
||||
/// </summary>
|
||||
internal sealed partial class LineHandler
|
||||
{
|
||||
private void DrawPolarLine(VertexHelper vh, Serie serie)
|
||||
{
|
||||
var datas = serie.data;
|
||||
if (datas.Count <= 0)
|
||||
return;
|
||||
|
||||
var m_Polar = chart.GetChartComponent<PolarCoord>(serie.polarIndex);
|
||||
if (m_Polar == null)
|
||||
return;
|
||||
|
||||
var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, m_Polar.index);
|
||||
var m_RadiusAxis = ComponentHelper.GetRadiusAxis(chart.components, m_Polar.index);
|
||||
if (m_AngleAxis == null || m_RadiusAxis == null)
|
||||
return;
|
||||
|
||||
var startAngle = m_AngleAxis.startAngle;
|
||||
var radius = m_Polar.context.radius;
|
||||
|
||||
var min = m_RadiusAxis.context.minValue;
|
||||
var max = m_RadiusAxis.context.maxValue;
|
||||
var firstSerieData = datas[0];
|
||||
var startPos = GetPolarPos(m_Polar, m_AngleAxis, firstSerieData, min, max, radius);
|
||||
var nextPos = Vector3.zero;
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serie.index, serie.highlight);
|
||||
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
var currDetailProgress = 0f;
|
||||
var totalDetailProgress = datas.Count;
|
||||
|
||||
serie.animation.InitProgress(currDetailProgress, totalDetailProgress);
|
||||
|
||||
for (int i = 1; i < datas.Count; i++)
|
||||
{
|
||||
if (serie.animation.CheckDetailBreak(i))
|
||||
break;
|
||||
|
||||
var serieData = datas[i];
|
||||
nextPos = GetPolarPos(m_Polar, m_AngleAxis, datas[i], min, max, radius);
|
||||
UGL.DrawLine(vh, startPos, nextPos, lineWidth, lineColor);
|
||||
startPos = nextPos;
|
||||
}
|
||||
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(totalDetailProgress);
|
||||
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
|
||||
chart.RefreshChart();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPolarLineSymbol(VertexHelper vh)
|
||||
{
|
||||
for (int n = 0; n < chart.series.Count; n++)
|
||||
{
|
||||
var serie = chart.series[n];
|
||||
|
||||
if (!serie.show)
|
||||
continue;
|
||||
if (!(serie is Line))
|
||||
continue;
|
||||
|
||||
var count = serie.dataCount;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var serieData = serie.GetSerieData(i);
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
if (ChartHelper.IsIngore(serieData.context.position))
|
||||
continue;
|
||||
|
||||
bool highlight = serieData.context.highlight || serie.highlight;
|
||||
if ((!symbol.show || !symbol.ShowSymbol(i, count) || serie.IsPerformanceMode())
|
||||
&& !serieData.context.highlight)
|
||||
continue;
|
||||
|
||||
var symbolSize = highlight
|
||||
? symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSize)
|
||||
: symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, n, highlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, n, highlight);
|
||||
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, n, highlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, highlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
|
||||
|
||||
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
|
||||
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, serieData.context.position,
|
||||
symbolColor, symbolToColor, symbolEmptyColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 GetPolarPos(PolarCoord m_Polar, AngleAxis m_AngleAxis, SerieData serieData, double min,
|
||||
double max, float polarRadius)
|
||||
{
|
||||
var angle = 0f;
|
||||
|
||||
if (!m_AngleAxis.clockwise)
|
||||
{
|
||||
angle = m_AngleAxis.startAngle - (float)serieData.GetData(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = m_AngleAxis.startAngle + (float)serieData.GetData(1);
|
||||
}
|
||||
|
||||
var value = serieData.GetData(0);
|
||||
var radius = (float)((value - min) / (max - min) * polarRadius);
|
||||
|
||||
angle = (angle + 360) % 360;
|
||||
serieData.context.angle = angle;
|
||||
serieData.context.position = ChartHelper.GetPos(m_Polar.context.center, radius, angle, true);
|
||||
|
||||
return serieData.context.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Line/LineHandler.PolarCoord.cs.meta
Normal file
11
Runtime/Serie/Line/LineHandler.PolarCoord.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8655c97b8c7e44e44852f8b81a7372b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
451
Runtime/Serie/Line/LineHelper.cs
Normal file
451
Runtime/Serie/Line/LineHelper.cs
Normal file
@@ -0,0 +1,451 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class LineHelper
|
||||
{
|
||||
private static List<Vector3> s_CurvesPosList = new List<Vector3>();
|
||||
|
||||
public static int GetDataAverageRate(Serie serie, GridCoord grid, int maxCount, bool isYAxis)
|
||||
{
|
||||
var sampleDist = serie.sampleDist;
|
||||
var rate = 0;
|
||||
var width = isYAxis ? grid.context.height : grid.context.width;
|
||||
if (sampleDist > 0)
|
||||
rate = (int)((maxCount - serie.minShow) / (width / sampleDist));
|
||||
if (rate < 1)
|
||||
rate = 1;
|
||||
return rate;
|
||||
}
|
||||
|
||||
public static void DrawSerieLineArea(VertexHelper vh, Serie serie, Serie lastStackSerie,
|
||||
ThemeStyle theme, bool isY, Axis axis, Axis relativedAxis, GridCoord grid)
|
||||
{
|
||||
if (serie.areaStyle == null || !serie.areaStyle.show)
|
||||
return;
|
||||
|
||||
var srcAreaColor = SerieHelper.GetAreaColor(serie, theme, serie.context.colorIndex, false);
|
||||
var srcAreaToColor = SerieHelper.GetAreaToColor(serie, theme, serie.context.colorIndex, false);
|
||||
var gridXY = (isY ? grid.context.x : grid.context.y);
|
||||
if (lastStackSerie == null)
|
||||
{
|
||||
LineHelper.DrawSerieLineNormalArea(vh, serie, isY,
|
||||
gridXY + relativedAxis.context.offset,
|
||||
gridXY,
|
||||
gridXY + (isY ? grid.context.width : grid.context.height),
|
||||
srcAreaColor,
|
||||
srcAreaToColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
LineHelper.DrawSerieLineStackArea(vh, serie, lastStackSerie, isY,
|
||||
gridXY + relativedAxis.context.offset,
|
||||
gridXY,
|
||||
gridXY + (isY ? grid.context.width : grid.context.height),
|
||||
srcAreaColor,
|
||||
srcAreaToColor);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawSerieLineNormalArea(VertexHelper vh, Serie serie, bool isY,
|
||||
float zero, float min, float max, Color32 color, Color32 toColor)
|
||||
{
|
||||
var points = serie.context.drawPoints;
|
||||
var count = points.Count;
|
||||
if (count < 2)
|
||||
return;
|
||||
|
||||
var isBreak = false;
|
||||
var lp = Vector3.zero;
|
||||
var lerp = !ChartHelper.IsValueEqualsColor(color, toColor);
|
||||
var zsp = isY
|
||||
? new Vector3(zero, points[0].position.y)
|
||||
: new Vector3(points[0].position.x, zero);
|
||||
var zep = isY
|
||||
? new Vector3(zero, points[count - 1].position.y)
|
||||
: new Vector3(points[count - 1].position.x, zero);
|
||||
|
||||
var lastDataIsIgnore = false;
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
var tp = points[i].position;
|
||||
var isIgnore = points[i].isIgnoreBreak;
|
||||
|
||||
if (serie.animation.CheckDetailBreak(tp, isY))
|
||||
{
|
||||
isBreak = true;
|
||||
|
||||
var progress = serie.animation.GetCurrDetail();
|
||||
var ip = Vector3.zero;
|
||||
var axisStartPos = isY ? new Vector3(-10000, progress) : new Vector3(progress, -10000);
|
||||
var axisEndPos = isY ? new Vector3(10000, progress) : new Vector3(progress, 10000);
|
||||
|
||||
if (UGLHelper.GetIntersection(lp, tp, axisStartPos, axisEndPos, ref ip))
|
||||
tp = ip;
|
||||
}
|
||||
|
||||
var zp = isY ? new Vector3(zero, tp.y) : new Vector3(tp.x, zero);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
if ((lp.y - zero > 0 && tp.y - zero < 0) || (lp.y - zero < 0 && tp.y - zero > 0))
|
||||
{
|
||||
var ip = Vector3.zero;
|
||||
if (UGLHelper.GetIntersection(lp, tp, zsp, zep, ref ip))
|
||||
{
|
||||
if (lerp)
|
||||
AddVertToVertexHelperWithLerpColor(vh, ip, ip, color, toColor, isY, min, max, i > 0);
|
||||
else
|
||||
{
|
||||
if (lastDataIsIgnore)
|
||||
UGL.AddVertToVertexHelper(vh, ip, ip, ColorUtil.clearColor32, true);
|
||||
|
||||
UGL.AddVertToVertexHelper(vh, ip, ip, toColor, color, i > 0);
|
||||
|
||||
if (isIgnore)
|
||||
UGL.AddVertToVertexHelper(vh, ip, ip, ColorUtil.clearColor32, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lerp)
|
||||
AddVertToVertexHelperWithLerpColor(vh, tp, zp, color, toColor, isY, min, max, i > 0);
|
||||
else
|
||||
{
|
||||
if (lastDataIsIgnore)
|
||||
UGL.AddVertToVertexHelper(vh, tp, zp, ColorUtil.clearColor32, true);
|
||||
|
||||
UGL.AddVertToVertexHelper(vh, tp, zp, toColor, color, i > 0);
|
||||
|
||||
if (isIgnore)
|
||||
UGL.AddVertToVertexHelper(vh, tp, zp, ColorUtil.clearColor32, true);
|
||||
}
|
||||
lp = tp;
|
||||
lastDataIsIgnore = isIgnore;
|
||||
if (isBreak)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawSerieLineStackArea(VertexHelper vh, Serie serie, Serie lastStackSerie, bool isY,
|
||||
float zero, float min, float max, Color32 color, Color32 toColor)
|
||||
{
|
||||
if (lastStackSerie == null)
|
||||
return;
|
||||
|
||||
var upPoints = serie.context.drawPoints;
|
||||
var downPoints = lastStackSerie.context.drawPoints;
|
||||
var upCount = upPoints.Count;
|
||||
var downCount = downPoints.Count;
|
||||
|
||||
if (upCount <= 0 || downCount <= 0)
|
||||
return;
|
||||
|
||||
var lerp = !ChartHelper.IsValueEqualsColor(color, toColor);
|
||||
var ltp = upPoints[0].position;
|
||||
var lbp = downPoints[0].position;
|
||||
|
||||
if (lerp)
|
||||
AddVertToVertexHelperWithLerpColor(vh, ltp, lbp, color, toColor, isY, min, max, false);
|
||||
else
|
||||
UGL.AddVertToVertexHelper(vh, ltp, lbp, color, false);
|
||||
|
||||
int u = 1, d = 1;
|
||||
var isBreakTop = false;
|
||||
var isBreakBottom = false;
|
||||
|
||||
while ((u < upCount || d < downCount))
|
||||
{
|
||||
var tp = u < upCount ? upPoints[u].position : upPoints[upCount - 1].position;
|
||||
var bp = d < downCount ? downPoints[d].position : downPoints[downCount - 1].position;
|
||||
|
||||
var tnp = (u + 1) < upCount ? upPoints[u + 1].position : upPoints[upCount - 1].position;
|
||||
var bnp = (d + 1) < downCount ? downPoints[d + 1].position : downPoints[downCount - 1].position;
|
||||
|
||||
if (serie.animation.CheckDetailBreak(tp, isY))
|
||||
{
|
||||
isBreakTop = true;
|
||||
|
||||
var progress = serie.animation.GetCurrDetail();
|
||||
var ip = Vector3.zero;
|
||||
|
||||
if (UGLHelper.GetIntersection(ltp, tp,
|
||||
new Vector3(progress, -10000),
|
||||
new Vector3(progress, 10000), ref ip))
|
||||
tp = ip;
|
||||
else
|
||||
tp = new Vector3(progress, tp.y);
|
||||
}
|
||||
if (serie.animation.CheckDetailBreak(bp, isY))
|
||||
{
|
||||
isBreakBottom = true;
|
||||
|
||||
var progress = serie.animation.GetCurrDetail();
|
||||
var ip = Vector3.zero;
|
||||
|
||||
if (UGLHelper.GetIntersection(lbp, bp,
|
||||
new Vector3(progress, -10000),
|
||||
new Vector3(progress, 10000), ref ip))
|
||||
bp = ip;
|
||||
else
|
||||
bp = new Vector3(progress, bp.y);
|
||||
}
|
||||
|
||||
if (lerp)
|
||||
AddVertToVertexHelperWithLerpColor(vh, tp, bp, color, toColor, isY, min, max, true);
|
||||
else
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, color, true);
|
||||
u++;
|
||||
d++;
|
||||
if (bp.x < tp.x && bnp.x < tp.x)
|
||||
u--;
|
||||
if (tp.x < bp.x && tnp.x < bp.x)
|
||||
d--;
|
||||
|
||||
ltp = tp;
|
||||
lbp = bp;
|
||||
if (isBreakTop && isBreakBottom)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddVertToVertexHelperWithLerpColor(VertexHelper vh, Vector3 tp, Vector3 bp,
|
||||
Color32 color, Color32 toColor, bool isY, float min, float max, bool needTriangle)
|
||||
{
|
||||
var range = max - min;
|
||||
var color1 = Color32.Lerp(color, toColor, ((isY ? tp.x : tp.y) - min) / range);
|
||||
var color2 = Color32.Lerp(color, toColor, ((isY ? bp.x : bp.y) - min) / range);
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
|
||||
}
|
||||
|
||||
internal static void DrawSerieLine(VertexHelper vh, ThemeStyle theme, Serie serie, VisualMap visualMap,
|
||||
GridCoord grid, Axis axis, Axis relativedAxis, float lineWidth)
|
||||
{
|
||||
var datas = serie.context.drawPoints;
|
||||
|
||||
var dataCount = datas.Count;
|
||||
if (dataCount < 2)
|
||||
return;
|
||||
|
||||
var ltp = Vector3.zero;
|
||||
var lbp = Vector3.zero;
|
||||
var ntp = Vector3.zero;
|
||||
var nbp = Vector3.zero;
|
||||
var itp = Vector3.zero;
|
||||
var ibp = Vector3.zero;
|
||||
var clp = Vector3.zero;
|
||||
var crp = Vector3.zero;
|
||||
|
||||
var isBreak = false;
|
||||
var isY = axis is YAxis;
|
||||
var isVisualMapGradient = VisualMapHelper.IsNeedGradient(visualMap);
|
||||
var isLineStyleGradient = serie.lineStyle.IsNeedGradient();
|
||||
|
||||
//var highlight = serie.highlight || serie.context.pointerEnter;
|
||||
var lineColor = SerieHelper.GetLineColor(serie, theme, serie.context.colorIndex, false);
|
||||
|
||||
var lastDataIsIgnore = datas[0].isIgnoreBreak;
|
||||
for (int i = 1; i < dataCount; i++)
|
||||
{
|
||||
var cdata = datas[i];
|
||||
var isIgnore = cdata.isIgnoreBreak;
|
||||
|
||||
var cp = cdata.position;
|
||||
var lp = datas[i - 1].position;
|
||||
|
||||
var np = i == dataCount - 1 ? cp : datas[i + 1].position;
|
||||
if (serie.animation.CheckDetailBreak(cp, isY))
|
||||
{
|
||||
isBreak = true;
|
||||
var ip = Vector3.zero;
|
||||
var progress = serie.animation.GetCurrDetail();
|
||||
if (AnimationStyleHelper.GetAnimationPosition(serie.animation, isY, lp, cp, progress, ref ip))
|
||||
cp = np = ip;
|
||||
}
|
||||
bool bitp = true, bibp = true;
|
||||
UGLHelper.GetLinePoints(lp, cp, np, lineWidth,
|
||||
ref ltp, ref lbp,
|
||||
ref ntp, ref nbp,
|
||||
ref itp, ref ibp,
|
||||
ref clp, ref crp,
|
||||
ref bitp, ref bibp, i);
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
AddLineVertToVertexHelper(vh, ltp, lbp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, false, lastDataIsIgnore, isIgnore);
|
||||
}
|
||||
|
||||
if (bitp == bibp)
|
||||
{
|
||||
if (bitp)
|
||||
AddLineVertToVertexHelper(vh, itp, ibp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
else
|
||||
{
|
||||
AddLineVertToVertexHelper(vh, ltp, clp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
AddLineVertToVertexHelper(vh, ltp, crp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bitp)
|
||||
{
|
||||
AddLineVertToVertexHelper(vh, itp, clp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
AddLineVertToVertexHelper(vh, itp, crp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
}
|
||||
else if (bibp)
|
||||
{
|
||||
AddLineVertToVertexHelper(vh, clp, ibp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
AddLineVertToVertexHelper(vh, crp, ibp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||
}
|
||||
}
|
||||
lastDataIsIgnore = isIgnore;
|
||||
if (isBreak)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetLineWidth(ref bool interacting, Serie serie, float defaultWidth)
|
||||
{
|
||||
var lineWidth = 0f;
|
||||
if (!serie.interact.TryGetValue(ref lineWidth, ref interacting))
|
||||
{
|
||||
lineWidth = serie.lineStyle.GetWidth(defaultWidth);
|
||||
serie.interact.SetValue(ref interacting, lineWidth);
|
||||
}
|
||||
return lineWidth;
|
||||
}
|
||||
|
||||
private static void AddLineVertToVertexHelper(VertexHelper vh, Vector3 tp, Vector3 bp,
|
||||
Color32 lineColor, bool visualMapGradient, bool lineStyleGradient, VisualMap visualMap,
|
||||
LineStyle lineStyle, GridCoord grid, Axis axis, Axis relativedAxis, bool needTriangle,
|
||||
bool lastIgnore, bool ignore)
|
||||
{
|
||||
if (lastIgnore && needTriangle)
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, true);
|
||||
|
||||
if (visualMapGradient)
|
||||
{
|
||||
var color1 = VisualMapHelper.GetLineGradientColor(visualMap, tp, grid, axis, relativedAxis, lineColor);
|
||||
var color2 = VisualMapHelper.GetLineGradientColor(visualMap, bp, grid, axis, relativedAxis, lineColor);
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
|
||||
}
|
||||
else if (lineStyleGradient)
|
||||
{
|
||||
var color1 = VisualMapHelper.GetLineStyleGradientColor(lineStyle, tp, grid, axis, lineColor);
|
||||
var color2 = VisualMapHelper.GetLineStyleGradientColor(lineStyle, bp, grid, axis, lineColor);
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, lineColor, needTriangle);
|
||||
}
|
||||
if (lastIgnore && !needTriangle)
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
|
||||
if (ignore && needTriangle)
|
||||
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
|
||||
}
|
||||
|
||||
internal static void UpdateSerieDrawPoints(Serie serie, Settings setting, ThemeStyle theme, float lineWidth, bool isY = false)
|
||||
{
|
||||
|
||||
serie.context.drawPoints.Clear();
|
||||
var last = Vector3.zero;
|
||||
switch (serie.lineType)
|
||||
{
|
||||
case LineType.Smooth:
|
||||
UpdateSmoothLineDrawPoints(serie, setting, isY);
|
||||
break;
|
||||
case LineType.StepStart:
|
||||
case LineType.StepMiddle:
|
||||
case LineType.StepEnd:
|
||||
UpdateStepLineDrawPoints(serie, setting, theme, isY, lineWidth);
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < serie.context.dataPoints.Count; i++)
|
||||
{
|
||||
serie.context.drawPoints.Add(new PointInfo(serie.context.dataPoints[i], serie.context.dataIgnores[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateSmoothLineDrawPoints(Serie serie, Settings setting, bool isY)
|
||||
{
|
||||
var points = serie.context.dataPoints;
|
||||
float smoothness = setting.lineSmoothness;
|
||||
for (int i = 0; i < points.Count - 1; i++)
|
||||
{
|
||||
var sp = points[i];
|
||||
var ep = points[i + 1];
|
||||
var lsp = i > 0 ? points[i - 1] : sp;
|
||||
var nep = i < points.Count - 2 ? points[i + 2] : ep;
|
||||
var ignore = serie.context.dataIgnores[i];
|
||||
if (isY)
|
||||
UGLHelper.GetBezierListVertical(ref s_CurvesPosList, sp, ep, smoothness);
|
||||
else
|
||||
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness);
|
||||
|
||||
for (int j = 1; j < s_CurvesPosList.Count; j++)
|
||||
{
|
||||
serie.context.drawPoints.Add(new PointInfo(s_CurvesPosList[j], ignore));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateStepLineDrawPoints(Serie serie, Settings setting, ThemeStyle theme, bool isY, float lineWidth)
|
||||
{
|
||||
var points = serie.context.dataPoints;
|
||||
var lp = points[0];
|
||||
serie.context.drawPoints.Clear();
|
||||
serie.context.drawPoints.Add(new PointInfo(lp, serie.context.dataIgnores[0]));
|
||||
for (int i = 1; i < points.Count; i++)
|
||||
{
|
||||
var cp = points[i];
|
||||
var ignore = serie.context.dataIgnores[i];
|
||||
if ((isY && Mathf.Abs(lp.x - cp.x) <= lineWidth)
|
||||
|| (!isY && Mathf.Abs(lp.y - cp.y) <= lineWidth))
|
||||
{
|
||||
serie.context.drawPoints.Add(new PointInfo(cp, ignore));
|
||||
lp = cp;
|
||||
continue;
|
||||
}
|
||||
switch (serie.lineType)
|
||||
{
|
||||
case LineType.StepStart:
|
||||
serie.context.drawPoints.Add(new PointInfo(isY
|
||||
? new Vector3(cp.x, lp.y)
|
||||
: new Vector3(lp.x, cp.y), ignore));
|
||||
break;
|
||||
case LineType.StepMiddle:
|
||||
serie.context.drawPoints.Add(new PointInfo(isY
|
||||
? new Vector3(lp.x, (lp.y + cp.y) / 2)
|
||||
: new Vector3((lp.x + cp.x) / 2, lp.y), ignore));
|
||||
serie.context.drawPoints.Add(new PointInfo(isY
|
||||
? new Vector3(cp.x, (lp.y + cp.y) / 2)
|
||||
: new Vector3((lp.x + cp.x) / 2, cp.y), ignore));
|
||||
break;
|
||||
case LineType.StepEnd:
|
||||
serie.context.drawPoints.Add(new PointInfo(isY
|
||||
? new Vector3(lp.x, cp.y)
|
||||
: new Vector3(cp.x, lp.y), ignore));
|
||||
break;
|
||||
}
|
||||
serie.context.drawPoints.Add(new PointInfo(cp, ignore));
|
||||
lp = cp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Line/LineHelper.cs.meta
Normal file
11
Runtime/Serie/Line/LineHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7292748fb01ef44709a94d08f4907dd5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
39
Runtime/Serie/Line/SimplifiedLine.cs
Normal file
39
Runtime/Serie/Line/SimplifiedLine.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[Serializable]
|
||||
[SerieHandler(typeof(SimplifiedLineHandler), true)]
|
||||
[SerieConvert(typeof(SimplifiedBar), typeof(Line))]
|
||||
[CoordOptions(typeof(GridCoord))]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[SerieExtraComponent(typeof(AreaStyle))]
|
||||
public class SimplifiedLine : Serie, INeedSerieContainer, ISimplifiedSerie
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<SimplifiedLine>(serieName);
|
||||
serie.symbol.show = false;
|
||||
var lastValue = 0d;
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
if (i < 20)
|
||||
lastValue += UnityEngine.Random.Range(0, 5);
|
||||
else
|
||||
lastValue += UnityEngine.Random.Range(-3, 5);
|
||||
chart.AddData(serie.index, lastValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static SimplifiedLine CovertSerie(Serie serie)
|
||||
{
|
||||
var newSerie = serie.Clone<SimplifiedLine>();
|
||||
return newSerie;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Line/SimplifiedLine.cs.meta
Normal file
11
Runtime/Serie/Line/SimplifiedLine.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5740626e12a84a0ca3a984935f61720
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
281
Runtime/Serie/Line/SimplifiedLineHandler.cs
Normal file
281
Runtime/Serie/Line/SimplifiedLineHandler.cs
Normal file
@@ -0,0 +1,281 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
/// <summary>
|
||||
/// For grid coord
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class SimplifiedLineHandler : SerieHandler<SimplifiedLine>
|
||||
{
|
||||
private GridCoord m_SerieGrid;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
|
||||
marker, itemFormatter, numericFormatter);
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
DrawLineSerie(vh, serie);
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
|
||||
var lineWidth = 0f;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag != needCheck)
|
||||
{
|
||||
var needAnimation1 = false;
|
||||
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
serie.interact.SetValue(ref needAnimation1, lineWidth, false);
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needAnimation1, symbolSize);
|
||||
}
|
||||
if (needAnimation1)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
|
||||
var themeSymbolSelectedSize = chart.theme.serie.lineSymbolSelectedSize;
|
||||
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
|
||||
var needInteract = false;
|
||||
if (m_LegendEnter)
|
||||
{
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
}
|
||||
else if (serie.context.isTriggerByAxis)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
|
||||
if (i == serie.context.pointerItemDataIndex)
|
||||
{
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var dist = Vector3.Distance(chart.pointerPos, serieData.context.position);
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
|
||||
if (dist <= symbolSelectedSize)
|
||||
{
|
||||
serie.context.pointerItemDataIndex = serieData.index;
|
||||
serie.context.pointerEnter = true;
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true);
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLineSerie(VertexHelper vh, SimplifiedLine serie)
|
||||
{
|
||||
if (!serie.show)
|
||||
return;
|
||||
if (serie.animation.HasFadeOut())
|
||||
return;
|
||||
|
||||
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
|
||||
|
||||
Axis axis;
|
||||
Axis relativedAxis;
|
||||
|
||||
if (isY)
|
||||
{
|
||||
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
}
|
||||
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
|
||||
|
||||
if (axis == null)
|
||||
return;
|
||||
if (relativedAxis == null)
|
||||
return;
|
||||
if (m_SerieGrid == null)
|
||||
return;
|
||||
|
||||
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
|
||||
if (showData.Count <= 0)
|
||||
return;
|
||||
|
||||
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
|
||||
var scaleWid = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
|
||||
|
||||
int maxCount = serie.maxShow > 0
|
||||
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
int rate = LineHelper.GetDataAverageRate(serie, m_SerieGrid, maxCount, false);
|
||||
var totalAverage = serie.sampleAverage > 0
|
||||
? serie.sampleAverage
|
||||
: DataHelper.DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
|
||||
var dataChanging = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
|
||||
var interacting = false;
|
||||
var lineWidth = LineHelper.GetLineWidth(ref interacting, serie, chart.theme.serie.lineWidth);
|
||||
|
||||
axis.context.scaleWidth = scaleWid;
|
||||
serie.containerIndex = m_SerieGrid.index;
|
||||
serie.containterInstanceId = m_SerieGrid.instanceId;
|
||||
|
||||
for (int i = serie.minShow; i < maxCount; i += rate)
|
||||
{
|
||||
var serieData = showData[i];
|
||||
var isIgnore = serie.IsIgnoreValue(serieData);
|
||||
if (isIgnore)
|
||||
{
|
||||
serieData.context.stackHeight = 0;
|
||||
serieData.context.position = Vector3.zero;
|
||||
if (serie.ignoreLineBreak && serie.context.dataIgnores.Count > 0)
|
||||
{
|
||||
serie.context.dataIgnores[serie.context.dataIgnores.Count - 1] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var np = Vector3.zero;
|
||||
var xValue = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
|
||||
var relativedValue = DataHelper.SampleValue(ref showData, serie.sampleType, rate, serie.minShow,
|
||||
maxCount, totalAverage, i, dataChangeDuration, ref dataChanging, relativedAxis);
|
||||
|
||||
serieData.context.stackHeight = GetDataPoint(isY, axis, relativedAxis, m_SerieGrid, xValue, relativedValue,
|
||||
i, scaleWid, false, ref np);
|
||||
|
||||
serieData.context.position = np;
|
||||
|
||||
serie.context.dataPoints.Add(np);
|
||||
serie.context.dataIgnores.Add(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataChanging || interacting)
|
||||
chart.RefreshPainter(serie);
|
||||
|
||||
if (serie.context.dataPoints.Count <= 0)
|
||||
return;
|
||||
|
||||
serie.animation.InitProgress(serie.context.dataPoints, isY);
|
||||
|
||||
LineHelper.UpdateSerieDrawPoints(serie, chart.settings, chart.theme, lineWidth, isY);
|
||||
LineHelper.DrawSerieLineArea(vh, serie, null, chart.theme, isY, axis, relativedAxis, m_SerieGrid);
|
||||
LineHelper.DrawSerieLine(vh, chart.theme, serie, null, m_SerieGrid, axis, relativedAxis, lineWidth);
|
||||
|
||||
serie.context.vertCount = vh.currentVertCount;
|
||||
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private float GetDataPoint(bool isY, Axis axis, Axis relativedAxis, GridCoord grid, double xValue,
|
||||
double yValue, int i, float scaleWid, bool isStack, ref Vector3 np)
|
||||
{
|
||||
float xPos, yPos;
|
||||
var gridXY = isY ? grid.context.x : grid.context.y;
|
||||
|
||||
if (isY)
|
||||
{
|
||||
var valueHig = AxisHelper.GetAxisValueLength(grid, relativedAxis, scaleWid, yValue);
|
||||
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
|
||||
|
||||
xPos = gridXY + valueHig;
|
||||
yPos = AxisHelper.GetAxisPosition(grid, axis, scaleWid, xValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var valueHig = AxisHelper.GetAxisValueLength(grid, relativedAxis, scaleWid, yValue);
|
||||
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
|
||||
|
||||
yPos = gridXY + valueHig;
|
||||
xPos = AxisHelper.GetAxisPosition(grid, axis, scaleWid, xValue);
|
||||
}
|
||||
np = new Vector3(xPos, yPos);
|
||||
return yPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Line/SimplifiedLineHandler.cs.meta
Normal file
11
Runtime/Serie/Line/SimplifiedLineHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c4714bd08de34548ac7be3ec6523ee1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Liquid.meta
Normal file
8
Runtime/Serie/Liquid.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 296736becc9a041c8ac957be56db7c8f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
67
Runtime/Serie/Liquid/Liquid.cs
Normal file
67
Runtime/Serie/Liquid/Liquid.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(LiquidHandler), true)]
|
||||
[RequireChartComponent(typeof(Vessel))]
|
||||
[SerieExtraComponent()]
|
||||
public class Liquid : Serie, INeedSerieContainer
|
||||
{
|
||||
[SerializeField] private float m_WaveHeight = 10f;
|
||||
[SerializeField] private float m_WaveLength = 20f;
|
||||
[SerializeField] private float m_WaveSpeed = 5f;
|
||||
[SerializeField] private float m_WaveOffset = 0f;
|
||||
/// <summary>
|
||||
/// Wave length of the wave, which is relative to the diameter.
|
||||
/// 波长。为0-1小数时指直线的百分比。
|
||||
/// </summary>
|
||||
public float waveLength
|
||||
{
|
||||
get { return m_WaveLength; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_WaveLength, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// 波高。
|
||||
/// </summary>
|
||||
public float waveHeight
|
||||
{
|
||||
get { return m_WaveHeight; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_WaveHeight, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// 波偏移。
|
||||
/// </summary>
|
||||
public float waveOffset
|
||||
{
|
||||
get { return m_WaveOffset; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_WaveOffset, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// 波速。正数时左移,负数时右移。
|
||||
/// </summary>
|
||||
public float waveSpeed
|
||||
{
|
||||
get { return m_WaveSpeed; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_WaveSpeed, value)) SetVerticesDirty(); }
|
||||
}
|
||||
|
||||
public int containerIndex { get { return vesselIndex; } }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
chart.AddChartComponentWhenNoExist<Vessel>();
|
||||
var serie = chart.AddSerie<Liquid>(serieName);
|
||||
serie.min = 0;
|
||||
serie.max = 100;
|
||||
serie.AddExtraComponent<LabelStyle>();
|
||||
serie.label.show = true;
|
||||
serie.label.textStyle.fontSize = 40;
|
||||
serie.label.formatter = "{d}%";
|
||||
serie.label.textStyle.color = new Color32(70, 70, 240, 255);
|
||||
chart.AddData(serie.index, UnityEngine.Random.Range(0, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Liquid/Liquid.cs.meta
Normal file
11
Runtime/Serie/Liquid/Liquid.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5695e4d13541046f5b782ee6dfed489a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
371
Runtime/Serie/Liquid/LiquidHandler.cs
Normal file
371
Runtime/Serie/Liquid/LiquidHandler.cs
Normal file
@@ -0,0 +1,371 @@
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class LiquidHandler : SerieHandler<Liquid>
|
||||
{
|
||||
private bool m_UpdateLabelText = false;
|
||||
private float m_WaveSpeed;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (m_UpdateLabelText)
|
||||
{
|
||||
m_UpdateLabelText = false;
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie is Liquid)
|
||||
{
|
||||
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.serieName);
|
||||
SerieLabelHelper.SetLiquidLabelText(serie, chart.theme, colorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
UpdateRuntimeData(serie);
|
||||
DrawVesselBackground(vh, serie);
|
||||
DrawLiquid(vh, serie);
|
||||
DrawVessel(vh, serie);
|
||||
}
|
||||
|
||||
private void UpdateRuntimeData(Liquid serie)
|
||||
{
|
||||
Vessel vessel;
|
||||
if (chart.TryGetChartComponent<Vessel>(out vessel, serie.vesselIndex))
|
||||
{
|
||||
VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVesselBackground(VertexHelper vh, Liquid serie)
|
||||
{
|
||||
var vessel = chart.GetChartComponent<Vessel>(serie.vesselIndex);
|
||||
if (vessel != null)
|
||||
{
|
||||
if (vessel.backgroundColor.a != 0)
|
||||
{
|
||||
switch (vessel.shape)
|
||||
{
|
||||
case Vessel.Shape.Circle:
|
||||
var cenPos = vessel.context.center;
|
||||
var radius = vessel.context.radius;
|
||||
UGL.DrawCricle(vh, cenPos, vessel.context.innerRadius + vessel.gap, vessel.backgroundColor,
|
||||
chart.settings.cicleSmoothness);
|
||||
UGL.DrawDoughnut(vh, cenPos, vessel.context.innerRadius, vessel.context.innerRadius + vessel.gap,
|
||||
vessel.backgroundColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
break;
|
||||
case Vessel.Shape.Rect:
|
||||
UGL.DrawRectangle(vh, vessel.context.center, vessel.context.width / 2, vessel.context.height / 2,
|
||||
vessel.backgroundColor);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVessel(VertexHelper vh, Liquid serie)
|
||||
{
|
||||
var vessel = chart.GetChartComponent<Vessel>(serie.vesselIndex);
|
||||
if (vessel != null)
|
||||
{
|
||||
switch (vessel.shape)
|
||||
{
|
||||
case Vessel.Shape.Circle:
|
||||
DrawCirleVessel(vh, vessel);
|
||||
break;
|
||||
case Vessel.Shape.Rect:
|
||||
DrawRectVessel(vh, vessel);
|
||||
break;
|
||||
default:
|
||||
DrawCirleVessel(vh, vessel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCirleVessel(VertexHelper vh, Vessel vessel)
|
||||
{
|
||||
var cenPos = vessel.context.center;
|
||||
var radius = vessel.context.radius;
|
||||
var serie = SeriesHelper.GetSerieByVesselIndex(chart.series, vessel.index);
|
||||
var vesselColor = VesselHelper.GetColor(vessel, serie, chart.theme, chart.m_LegendRealShowName);
|
||||
if (vessel.gap != 0)
|
||||
{
|
||||
UGL.DrawDoughnut(vh, cenPos, vessel.context.innerRadius, vessel.context.innerRadius + vessel.gap,
|
||||
vessel.backgroundColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
UGL.DrawDoughnut(vh, cenPos, radius - vessel.shapeWidth, radius, vesselColor, Color.clear,
|
||||
chart.settings.cicleSmoothness);
|
||||
}
|
||||
|
||||
private void DrawRectVessel(VertexHelper vh, Vessel vessel)
|
||||
{
|
||||
var serie = SeriesHelper.GetSerieByVesselIndex(chart.series, vessel.index);
|
||||
var vesselColor = VesselHelper.GetColor(vessel, serie, chart.theme, chart.m_LegendRealShowName);
|
||||
if (vessel.gap != 0)
|
||||
{
|
||||
UGL.DrawBorder(vh, vessel.context.center, vessel.context.width,
|
||||
vessel.context.height, vessel.gap, vessel.backgroundColor, 0, vessel.cornerRadius);
|
||||
}
|
||||
UGL.DrawBorder(vh, vessel.context.center, vessel.context.width + 2 * vessel.gap,
|
||||
vessel.context.height + 2 * vessel.gap, vessel.shapeWidth, vesselColor, 0, vessel.cornerRadius);
|
||||
}
|
||||
|
||||
private void DrawLiquid(VertexHelper vh, Liquid serie)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
var vessel = chart.GetChartComponent<Vessel>(serie.vesselIndex);
|
||||
if (vessel == null) return;
|
||||
switch (vessel.shape)
|
||||
{
|
||||
case Vessel.Shape.Circle:
|
||||
DrawCirleLiquid(vh, serie, vessel);
|
||||
break;
|
||||
case Vessel.Shape.Rect:
|
||||
DrawRectLiquid(vh, serie, vessel);
|
||||
break;
|
||||
default:
|
||||
DrawCirleLiquid(vh, serie, vessel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCirleLiquid(VertexHelper vh, Liquid serie, Vessel vessel)
|
||||
{
|
||||
var cenPos = vessel.context.center;
|
||||
var radius = vessel.context.innerRadius;
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var value = serieData.GetCurrData(1, dataChangeDuration);
|
||||
if (serie.context.checkValue != value)
|
||||
{
|
||||
serie.context.checkValue = value;
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
if (serieData.context.labelPosition != cenPos)
|
||||
{
|
||||
serieData.context.labelPosition = cenPos;
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
if (value <= 0) return;
|
||||
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.serieName);
|
||||
|
||||
var realHig = (float)((value - serie.min) / (serie.max - serie.min) * radius * 2);
|
||||
serie.animation.InitProgress(0, realHig);
|
||||
|
||||
var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail();
|
||||
var a = Mathf.Abs(radius - hig + (hig > radius ? serie.waveHeight : -serie.waveHeight));
|
||||
var diff = Mathf.Sqrt(radius * radius - Mathf.Pow(a, 2));
|
||||
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var isNeedGradient = !ChartHelper.IsValueEqualsColor(color, toColor);
|
||||
var isFull = hig >= 2 * radius;
|
||||
if (hig >= 2 * radius) hig = 2 * radius;
|
||||
if (isFull && !isNeedGradient)
|
||||
{
|
||||
UGL.DrawCricle(vh, cenPos, radius, toColor, chart.settings.cicleSmoothness);
|
||||
}
|
||||
else
|
||||
{
|
||||
var startY = cenPos.y - radius + hig;
|
||||
var waveStartPos = new Vector3(cenPos.x - diff, startY);
|
||||
var waveEndPos = new Vector3(cenPos.x + diff, startY);
|
||||
var startX = hig > radius ? cenPos.x - radius : waveStartPos.x;
|
||||
var endX = hig > radius ? cenPos.x + radius : waveEndPos.x;
|
||||
|
||||
var step = vessel.smoothness;
|
||||
if (step < 0.5f) step = 0.5f;
|
||||
var lup = hig > radius ? new Vector3(cenPos.x - radius, cenPos.y) : waveStartPos;
|
||||
var ldp = lup;
|
||||
var nup = Vector3.zero;
|
||||
var ndp = Vector3.zero;
|
||||
var angle = 0f;
|
||||
m_WaveSpeed += serie.waveSpeed * Time.deltaTime;
|
||||
var isStarted = false;
|
||||
var isEnded = false;
|
||||
var waveHeight = isFull ? 0 : serie.waveHeight;
|
||||
while (startX < endX)
|
||||
{
|
||||
startX += step;
|
||||
if (startX > endX) startX = endX;
|
||||
if (startX > waveStartPos.x && !isStarted)
|
||||
{
|
||||
startX = waveStartPos.x;
|
||||
isStarted = true;
|
||||
}
|
||||
if (startX > waveEndPos.x && !isEnded)
|
||||
{
|
||||
startX = waveEndPos.x;
|
||||
isEnded = true;
|
||||
}
|
||||
var py = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2));
|
||||
if (startX < waveStartPos.x || startX > waveEndPos.x)
|
||||
{
|
||||
nup = new Vector3(startX, cenPos.y + py);
|
||||
}
|
||||
else
|
||||
{
|
||||
var py2 = waveHeight * Mathf.Sin(1 / serie.waveLength * angle + m_WaveSpeed + serie.waveOffset);
|
||||
var nupY = waveStartPos.y + py2;
|
||||
if (nupY > cenPos.y + py) nupY = cenPos.y + py;
|
||||
else if (nupY < cenPos.y - py) nupY = cenPos.y - py;
|
||||
nup = new Vector3(startX, nupY);
|
||||
angle += step;
|
||||
}
|
||||
ndp = new Vector3(startX, cenPos.y - py);
|
||||
if (!ChartHelper.IsValueEqualsColor(color, toColor))
|
||||
{
|
||||
var colorMin = cenPos.y - radius;
|
||||
var colorMax = startY + serie.waveHeight;
|
||||
var tcolor1 = Color32.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin));
|
||||
var tcolor2 = Color32.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin));
|
||||
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, tcolor1, tcolor2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, color);
|
||||
}
|
||||
lup = nup;
|
||||
ldp = ndp;
|
||||
}
|
||||
}
|
||||
|
||||
if (serie.waveSpeed != 0 && Application.isPlaying && !isFull)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(realHig);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawRectLiquid(VertexHelper vh, Liquid serie, Vessel vessel)
|
||||
{
|
||||
var cenPos = vessel.context.center;
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var value = serieData.GetCurrData(1, dataChangeDuration);
|
||||
if (serie.context.checkValue != value)
|
||||
{
|
||||
serie.context.checkValue = value;
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
if (serieData.context.labelPosition != cenPos)
|
||||
{
|
||||
serieData.context.labelPosition = cenPos;
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
if (value <= 0) return;
|
||||
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.serieName);
|
||||
|
||||
var realHig = (value - serie.min) / (serie.max - serie.min) * vessel.context.height;
|
||||
serie.animation.InitProgress(0, (float)realHig);
|
||||
var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail();
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var isNeedGradient = !ChartHelper.IsValueEqualsColor(color, toColor);
|
||||
var isFull = hig >= vessel.context.height;
|
||||
if (hig >= vessel.context.height) hig = vessel.context.height;
|
||||
if (isFull && !isNeedGradient)
|
||||
{
|
||||
UGL.DrawRectangle(vh, cenPos, vessel.context.width / 2, vessel.context.height / 2, toColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
var startY = (float)(cenPos.y - vessel.context.height / 2 + hig);
|
||||
var waveStartPos = new Vector3(cenPos.x - vessel.context.width / 2, startY);
|
||||
var waveEndPos = new Vector3(cenPos.x + vessel.context.width / 2, startY);
|
||||
var startX = waveStartPos.x;
|
||||
var endX = waveEndPos.x;
|
||||
|
||||
var step = vessel.smoothness;
|
||||
if (step < 0.5f) step = 0.5f;
|
||||
var lup = waveStartPos;
|
||||
var ldp = new Vector3(startX, vessel.context.center.y - vessel.context.height / 2);
|
||||
var nup = Vector3.zero;
|
||||
var ndp = Vector3.zero;
|
||||
var angle = 0f;
|
||||
var isStarted = false;
|
||||
var isEnded = false;
|
||||
var waveHeight = isFull ? 0 : serie.waveHeight;
|
||||
m_WaveSpeed += serie.waveSpeed * Time.deltaTime;
|
||||
while (startX < endX)
|
||||
{
|
||||
startX += step;
|
||||
if (startX > endX) startX = endX;
|
||||
if (startX > waveStartPos.x && !isStarted)
|
||||
{
|
||||
startX = waveStartPos.x;
|
||||
isStarted = true;
|
||||
}
|
||||
if (startX > waveEndPos.x && !isEnded)
|
||||
{
|
||||
startX = waveEndPos.x;
|
||||
isEnded = true;
|
||||
}
|
||||
var py = Mathf.Sqrt(Mathf.Pow(vessel.context.height, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2));
|
||||
if (startX < waveStartPos.x || startX > waveEndPos.x)
|
||||
{
|
||||
nup = new Vector3(startX, cenPos.y + py);
|
||||
}
|
||||
else
|
||||
{
|
||||
var py2 = waveHeight * Mathf.Sin(1 / serie.waveLength * angle + m_WaveSpeed + serie.waveOffset);
|
||||
var nupY = waveStartPos.y + py2;
|
||||
nup = new Vector3(startX, nupY);
|
||||
angle += step;
|
||||
}
|
||||
|
||||
ndp = new Vector3(startX, cenPos.y - vessel.context.height / 2);
|
||||
if (nup.y > cenPos.y + vessel.context.height / 2)
|
||||
{
|
||||
nup.y = cenPos.y + vessel.context.height / 2;
|
||||
}
|
||||
if (nup.y < cenPos.y - vessel.context.height / 2)
|
||||
{
|
||||
nup.y = cenPos.y - vessel.context.height / 2;
|
||||
}
|
||||
if (!ChartHelper.IsValueEqualsColor(color, toColor))
|
||||
{
|
||||
var colorMin = cenPos.y - vessel.context.height;
|
||||
var colorMax = startY + serie.waveHeight;
|
||||
var tcolor1 = Color32.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin));
|
||||
var tcolor2 = Color32.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin));
|
||||
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, tcolor1, tcolor2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, color);
|
||||
}
|
||||
lup = nup;
|
||||
ldp = ndp;
|
||||
}
|
||||
}
|
||||
if (serie.waveSpeed != 0 && Application.isPlaying && !isFull)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(realHig);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Liquid/LiquidHandler.cs.meta
Normal file
11
Runtime/Serie/Liquid/LiquidHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afc0f085dba22490b8c727c29271bfe5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Parallel.meta
Normal file
8
Runtime/Serie/Parallel.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2ba7099a74f54617b446aeaf3d95672
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Runtime/Serie/Parallel/Parallel.cs
Normal file
33
Runtime/Serie/Parallel/Parallel.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(ParallelHandler), true)]
|
||||
[RequireChartComponent(typeof(ParallelCoord))]
|
||||
public class Parallel : Serie, INeedSerieContainer
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Parallel>(serieName);
|
||||
serie.lineStyle.width = 0.8f;
|
||||
serie.lineStyle.opacity = 0.6f;
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var data = new List<double>(){
|
||||
Random.Range(0f,50f),
|
||||
Random.Range(0f,100f),
|
||||
Random.Range(0f,1000f),
|
||||
Random.Range(0,5),
|
||||
};
|
||||
serie.AddData(data, "data" + i);
|
||||
}
|
||||
chart.RefreshChart();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Parallel/Parallel.cs.meta
Normal file
11
Runtime/Serie/Parallel/Parallel.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 283df79138f274a6ba975ff8f30c6d30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
153
Runtime/Serie/Parallel/ParallelHandler.cs
Normal file
153
Runtime/Serie/Parallel/ParallelHandler.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class ParallelHandler : SerieHandler<Parallel>
|
||||
{
|
||||
private List<Vector3> m_Points = new List<Vector3>();
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
DrawParallelSerie(vh, colorIndex, serie);
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
}
|
||||
|
||||
private void DrawParallelSerie(VertexHelper vh, int colorIndex, Parallel serie)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
|
||||
var parallel = chart.GetChartComponent<ParallelCoord>(serie.parallelIndex);
|
||||
if (parallel == null)
|
||||
return;
|
||||
|
||||
var axisCount = parallel.context.parallelAxes.Count;
|
||||
if (axisCount <= 0)
|
||||
return;
|
||||
|
||||
var animationIndex = serie.animation.GetCurrIndex();
|
||||
var isHorizonal = parallel.orient == Orient.Horizonal;
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, colorIndex, false);
|
||||
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
|
||||
float currDetailProgress = !isHorizonal
|
||||
? parallel.context.x
|
||||
: parallel.context.y;
|
||||
|
||||
float totalDetailProgress = !isHorizonal
|
||||
? parallel.context.x + parallel.context.width
|
||||
: parallel.context.y + parallel.context.height;
|
||||
|
||||
serie.animation.InitProgress(currDetailProgress, totalDetailProgress);
|
||||
|
||||
serie.context.dataPoints.Clear();
|
||||
serie.containerIndex = parallel.index;
|
||||
serie.containterInstanceId = parallel.instanceId;
|
||||
|
||||
var currProgress = serie.animation.GetCurrDetail();
|
||||
var isSmooth = serie.lineType == LineType.Smooth;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
m_Points.Clear();
|
||||
var count = Mathf.Min(axisCount, serieData.data.Count);
|
||||
var lp = Vector3.zero;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (animationIndex >= 0 && i > animationIndex) continue;
|
||||
var pos = GetPos(parallel, i, serieData.data[i], isHorizonal);
|
||||
if (!isHorizonal)
|
||||
{
|
||||
if (isSmooth)
|
||||
{
|
||||
m_Points.Add(pos);
|
||||
}
|
||||
else if (pos.x <= currProgress)
|
||||
{
|
||||
m_Points.Add(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
var currProgressStart = new Vector3(currProgress, parallel.context.y - 50);
|
||||
var currProgressEnd = new Vector3(currProgress, parallel.context.y + parallel.context.height + 50);
|
||||
var intersectionPos = Vector3.zero;
|
||||
|
||||
if (UGLHelper.GetIntersection(lp, pos, currProgressStart, currProgressEnd, ref intersectionPos))
|
||||
m_Points.Add(intersectionPos);
|
||||
else
|
||||
m_Points.Add(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isSmooth)
|
||||
{
|
||||
m_Points.Add(pos);
|
||||
}
|
||||
else if (pos.y <= currProgress)
|
||||
{
|
||||
m_Points.Add(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
var currProgressStart = new Vector3(parallel.context.x - 50, currProgress);
|
||||
var currProgressEnd = new Vector3(parallel.context.x + parallel.context.width + 50, currProgress);
|
||||
var intersectionPos = Vector3.zero;
|
||||
|
||||
if (UGLHelper.GetIntersection(lp, pos, currProgressStart, currProgressEnd, ref intersectionPos))
|
||||
m_Points.Add(intersectionPos);
|
||||
else
|
||||
m_Points.Add(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lp = pos;
|
||||
}
|
||||
if (isSmooth)
|
||||
UGL.DrawCurves(vh, m_Points, lineWidth, lineColor, chart.settings.lineSmoothness, currProgress, isHorizonal);
|
||||
else
|
||||
UGL.DrawLine(vh, m_Points, lineWidth, lineColor, isSmooth);
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(totalDetailProgress - currDetailProgress);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private static ParallelAxis GetAxis(ParallelCoord parallel, int index)
|
||||
{
|
||||
if (index >= 0 && index < parallel.context.parallelAxes.Count)
|
||||
return parallel.context.parallelAxes[index];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Vector3 GetPos(ParallelCoord parallel, int axisIndex, double dataValue, bool isHorizonal)
|
||||
{
|
||||
var axis = GetAxis(parallel, axisIndex);
|
||||
if (axis == null)
|
||||
return Vector3.zero;
|
||||
|
||||
var sValueDist = axis.GetDistance(dataValue, axis.context.width);
|
||||
return new Vector3(
|
||||
isHorizonal ? axis.context.x + sValueDist : axis.context.x,
|
||||
isHorizonal ? axis.context.y : axis.context.y + sValueDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Parallel/ParallelHandler.cs.meta
Normal file
11
Runtime/Serie/Parallel/ParallelHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 482b461d91f8c4013bf291153d5810e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Pie.meta
Normal file
8
Runtime/Serie/Pie.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5dfd0cb375a24f659bf56e113aa6fc8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Runtime/Serie/Pie/Pie.cs
Normal file
27
Runtime/Serie/Pie/Pie.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieConvert(typeof(Line), typeof(Bar))]
|
||||
[SerieHandler(typeof(PieHandler), true)]
|
||||
[DefaultAnimation(AnimationType.Clockwise)]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(LabelLine), typeof(IconStyle), typeof(Emphasis))]
|
||||
public class Pie : Serie
|
||||
{
|
||||
public override bool useDataNameForColor { get { return true; } }
|
||||
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Pie>(serieName);
|
||||
chart.AddData(serie.index, 70, "pie1");
|
||||
chart.AddData(serie.index, 20, "pie2");
|
||||
chart.AddData(serie.index, 10, "pie3");
|
||||
}
|
||||
|
||||
public static Pie CovertSerie(Serie serie)
|
||||
{
|
||||
var newSerie = SerieHelper.CloneSerie<Pie>(serie);
|
||||
return newSerie;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Pie/Pie.cs.meta
Normal file
11
Runtime/Serie/Pie/Pie.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53f0d225949a3450e9e90687759f1714
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
597
Runtime/Serie/Pie/PieHandler.cs
Normal file
597
Runtime/Serie/Pie/PieHandler.cs
Normal file
@@ -0,0 +1,597 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class PieHandler : SerieHandler<Pie>
|
||||
{
|
||||
public override void Update()
|
||||
{
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
UpdateRuntimeData(serie);
|
||||
DrawPieLabelLine(vh, serie);
|
||||
DrawPie(vh, serie);
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
UpdateItemSerieParams(ref paramList, ref title, dataIndex, category,
|
||||
marker, itemFormatter, numericFormatter);
|
||||
}
|
||||
|
||||
public override void RefreshLabelInternal()
|
||||
{
|
||||
var data = serie.data;
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
if (!serieData.context.canShowLabel || serie.IsIgnoreValue(serieData))
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
continue;
|
||||
}
|
||||
if (!serieData.show) continue;
|
||||
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.name);
|
||||
Color color = chart.theme.GetColor(colorIndex);
|
||||
DrawPieLabel(serie, n, serieData, color);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataShow(serie, legendName, show);
|
||||
chart.UpdateLegendColor(legendName, show);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataHighlighted(serie, legendName, true);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataHighlighted(serie, legendName, false);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (!chart.HasSerie<Pie>()) return;
|
||||
if (chart.pointerPos == Vector2.zero) return;
|
||||
var refresh = false;
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.GetSerie(i);
|
||||
if (!(serie is Pie)) continue;
|
||||
var index = GetPiePosIndex(serie, chart.pointerPos);
|
||||
if (index >= 0)
|
||||
{
|
||||
refresh = true;
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
if (j == index) serie.data[j].selected = !serie.data[j].selected;
|
||||
else serie.data[j].selected = false;
|
||||
}
|
||||
if (chart.onPointerClickPie != null)
|
||||
{
|
||||
chart.onPointerClickPie(eventData, i, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (refresh) chart.RefreshChart();
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
var needCheck = m_LegendEnter
|
||||
|| (chart.isPointerInChart && PointerIsInPieSerie(serie, chart.pointerPos));
|
||||
var needInteract = false;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag != needCheck)
|
||||
{
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
serieData.interact.SetValueAndColor(ref needInteract, serieData.context.outsideRadius, color, toColor);
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
var dataIndex = GetPiePosIndex(serie, chart.pointerPos);
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
if (dataIndex == i || (m_LegendEnter && m_LegendEnterIndex == i))
|
||||
{
|
||||
serie.context.pointerItemDataIndex = i;
|
||||
serieData.context.highlight = true;
|
||||
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, true);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, true);
|
||||
var value = serieData.context.outsideRadius + chart.theme.serie.pieTooltipExtraRadius;
|
||||
serieData.interact.SetValueAndColor(ref needInteract, value, color, toColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
serieData.interact.SetValueAndColor(ref needInteract, serieData.context.outsideRadius, color, toColor);
|
||||
}
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRuntimeData(Serie serie)
|
||||
{
|
||||
var data = serie.data;
|
||||
serie.context.dataMax = serie.yMax;
|
||||
var runtimePieDataTotal = serie.yTotal;
|
||||
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
float totalDegree = 0;
|
||||
float startDegree = 0;
|
||||
float zeroReplaceValue = 0;
|
||||
int showdataCount = 0;
|
||||
foreach (var sd in serie.data)
|
||||
{
|
||||
if (sd.show && serie.pieRoseType == RoseType.Area) showdataCount++;
|
||||
sd.context.canShowLabel = false;
|
||||
}
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
bool isAllZeroValue = SerieHelper.IsAllZeroValue(serie, 1);
|
||||
var dataTotalFilterMinAngle = runtimePieDataTotal;
|
||||
if (isAllZeroValue)
|
||||
{
|
||||
totalDegree = 360;
|
||||
zeroReplaceValue = totalDegree / data.Count;
|
||||
serie.context.dataMax = zeroReplaceValue;
|
||||
runtimePieDataTotal = 360;
|
||||
dataTotalFilterMinAngle = 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataTotalFilterMinAngle = GetTotalAngle(serie, runtimePieDataTotal, ref totalDegree);
|
||||
}
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
serieData.index = n;
|
||||
var value = isAllZeroValue ? zeroReplaceValue : serieData.GetCurrData(1, dataChangeDuration);
|
||||
serieData.context.startAngle = startDegree;
|
||||
serieData.context.toAngle = startDegree;
|
||||
serieData.context.halfAngle = startDegree;
|
||||
serieData.context.currentAngle = startDegree;
|
||||
if (!serieData.show)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float degree = serie.pieRoseType == RoseType.Area
|
||||
? (totalDegree / showdataCount)
|
||||
: (float)(totalDegree * value / dataTotalFilterMinAngle);
|
||||
if (serie.minAngle > 0 && degree < serie.minAngle) degree = serie.minAngle;
|
||||
serieData.context.toAngle = startDegree + degree;
|
||||
if (serieData.radius > 0)
|
||||
serieData.context.outsideRadius = serieData.radius;
|
||||
else
|
||||
serieData.context.outsideRadius = serie.pieRoseType > 0 ?
|
||||
serie.context.insideRadius + (float)((serie.context.outsideRadius - serie.context.insideRadius) * value / serie.context.dataMax) :
|
||||
serie.context.outsideRadius;
|
||||
if (serieData.context.highlight)
|
||||
{
|
||||
serieData.context.outsideRadius += chart.theme.serie.pieTooltipExtraRadius;
|
||||
}
|
||||
var offset = 0f;
|
||||
if (serie.pieClickOffset && serieData.selected)
|
||||
{
|
||||
offset += chart.theme.serie.pieSelectedOffset;
|
||||
}
|
||||
if (serie.animation.CheckDetailBreak(serieData.context.toAngle))
|
||||
{
|
||||
serieData.context.currentAngle = serie.animation.GetCurrDetail();
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.currentAngle = serieData.context.toAngle;
|
||||
}
|
||||
var halfDegree = (serieData.context.toAngle - startDegree) / 2;
|
||||
serieData.context.halfAngle = startDegree + halfDegree;
|
||||
serieData.context.offsetCenter = serie.context.center;
|
||||
serieData.context.insideRadius = serie.context.insideRadius;
|
||||
if (offset > 0)
|
||||
{
|
||||
var currRad = serieData.context.halfAngle * Mathf.Deg2Rad;
|
||||
var currSin = Mathf.Sin(currRad);
|
||||
var currCos = Mathf.Cos(currRad);
|
||||
serieData.context.offsetRadius = 0;
|
||||
serieData.context.insideRadius -= serieData.context.offsetRadius;
|
||||
serieData.context.outsideRadius -= serieData.context.offsetRadius;
|
||||
if (serie.pieClickOffset && serieData.selected)
|
||||
{
|
||||
serieData.context.offsetRadius += chart.theme.serie.pieSelectedOffset;
|
||||
if (serieData.context.insideRadius > 0)
|
||||
{
|
||||
serieData.context.insideRadius += chart.theme.serie.pieSelectedOffset;
|
||||
}
|
||||
serieData.context.outsideRadius += chart.theme.serie.pieSelectedOffset;
|
||||
}
|
||||
serieData.context.offsetCenter = new Vector3(
|
||||
serie.context.center.x + serieData.context.offsetRadius * currSin,
|
||||
serie.context.center.y + serieData.context.offsetRadius * currCos);
|
||||
}
|
||||
serieData.context.canShowLabel = serieData.context.currentAngle >= serieData.context.halfAngle;
|
||||
startDegree = serieData.context.toAngle;
|
||||
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
|
||||
}
|
||||
SerieLabelHelper.AvoidLabelOverlap(serie, chart.theme.common);
|
||||
}
|
||||
|
||||
private double GetTotalAngle(Serie serie, double dataTotal, ref float totalAngle)
|
||||
{
|
||||
totalAngle = 360f;
|
||||
if (serie.minAngle > 0)
|
||||
{
|
||||
var rate = serie.minAngle / 360;
|
||||
var minAngleValue = dataTotal * rate;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var value = serieData.GetData(1);
|
||||
if (value < minAngleValue)
|
||||
{
|
||||
totalAngle -= serie.minAngle;
|
||||
dataTotal -= value;
|
||||
}
|
||||
}
|
||||
return dataTotal;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dataTotal;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPieCenter(VertexHelper vh, Serie serie, ItemStyle itemStyle, float insideRadius)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(itemStyle.centerColor))
|
||||
{
|
||||
var radius = insideRadius - itemStyle.centerGap;
|
||||
UGL.DrawCricle(vh, serie.context.center, radius, itemStyle.centerColor, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (!serie.show || serie.animation.HasFadeOut())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var dataChanging = false;
|
||||
var interacting = false;
|
||||
var color = ColorUtil.clearColor32;
|
||||
var toColor = ColorUtil.clearColor32;
|
||||
var data = serie.data;
|
||||
serie.animation.InitProgress(0, 360);
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
if (!serieData.show)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (serieData.IsDataChanged())
|
||||
dataChanging = true;
|
||||
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.context.highlight);
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
|
||||
var outsideRadius = 0f;
|
||||
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
|
||||
var progress = AnimationStyleHelper.CheckDataAnimation(chart, serie, n, 1);
|
||||
var insideRadius = serieData.context.insideRadius * progress;
|
||||
|
||||
//if (!serieData.interact.TryGetValueAndColor(ref outsideRadius, ref color, ref toColor, ref interacting))
|
||||
{
|
||||
color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, serieData.context.highlight);
|
||||
toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, serieData.context.highlight);
|
||||
outsideRadius = serieData.context.outsideRadius * progress;
|
||||
serieData.interact.SetValueAndColor(ref interacting, outsideRadius, color, toColor);
|
||||
}
|
||||
|
||||
if (serie.pieClickOffset && serieData.selected)
|
||||
{
|
||||
var drawEndDegree = serieData.context.currentAngle;
|
||||
var needRoundCap = serie.roundCap && insideRadius > 0;
|
||||
UGL.DrawDoughnut(vh, serieData.context.offsetCenter, insideRadius,
|
||||
outsideRadius, color, toColor, Color.clear, serieData.context.startAngle,
|
||||
drawEndDegree, borderWidth, borderColor, serie.pieSpace / 2, chart.settings.cicleSmoothness,
|
||||
needRoundCap, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
var drawEndDegree = serieData.context.currentAngle;
|
||||
var needRoundCap = serie.roundCap && insideRadius > 0;
|
||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius,
|
||||
outsideRadius, color, toColor, Color.clear, serieData.context.startAngle,
|
||||
drawEndDegree, borderWidth, borderColor, serie.pieSpace / 2, chart.settings.cicleSmoothness,
|
||||
needRoundCap, true);
|
||||
DrawPieCenter(vh, serie, itemStyle, insideRadius);
|
||||
}
|
||||
|
||||
if (serie.animation.CheckDetailBreak(serieData.context.toAngle))
|
||||
break;
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress();
|
||||
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsAnyPieClickOffset()
|
||||
{
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie is Pie && serie.pieClickOffset) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsAnyPieDataHighlight()
|
||||
{
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie is Pie)
|
||||
{
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.context.highlight) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrawPieLabelLine(VertexHelper vh, Serie serie)
|
||||
{
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
|
||||
{
|
||||
int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);
|
||||
Color color = chart.theme.GetColor(colorIndex);
|
||||
DrawPieLabelLine(vh, serie, serieData, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPieLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color color)
|
||||
{
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||
if (serieLabel != null && serieLabel.show
|
||||
&& labelLine != null && labelLine.show
|
||||
&& serieLabel.position == LabelStyle.Position.Outside)
|
||||
{
|
||||
var insideRadius = serieData.context.insideRadius;
|
||||
var outSideRadius = serieData.context.outsideRadius;
|
||||
var center = serie.context.center;
|
||||
var currAngle = serieData.context.halfAngle;
|
||||
if (!ChartHelper.IsClearColor(labelLine.lineColor)) color = labelLine.lineColor;
|
||||
else if (labelLine.lineType == LabelLine.LineType.HorizontalLine) color *= color;
|
||||
float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad);
|
||||
float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad);
|
||||
var radius1 = labelLine.lineType == LabelLine.LineType.HorizontalLine ?
|
||||
serie.context.outsideRadius : outSideRadius;
|
||||
var radius2 = serie.context.outsideRadius + labelLine.lineLength1;
|
||||
var radius3 = insideRadius + (outSideRadius - insideRadius) / 2;
|
||||
if (radius1 < serie.context.insideRadius) radius1 = serie.context.insideRadius;
|
||||
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 = serieData.context.labelPosition;
|
||||
if (pos2.x == 0)
|
||||
{
|
||||
pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
|
||||
}
|
||||
Vector3 pos4, pos6;
|
||||
var horizontalLineCircleRadius = labelLine.lineWidth * 4f;
|
||||
var lineCircleDiff = horizontalLineCircleRadius - 0.3f;
|
||||
if (currAngle < 90)
|
||||
{
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
||||
r4 += labelLine.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.right * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.right * r4;
|
||||
}
|
||||
else if (currAngle < 180)
|
||||
{
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
||||
r4 += labelLine.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.right * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.right * r4;
|
||||
}
|
||||
else if (currAngle < 270)
|
||||
{
|
||||
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 += labelLine.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.left * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.left * r4;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 += labelLine.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.left * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.left * r4;
|
||||
}
|
||||
var pos5X = currAngle > 180 ? pos2.x - labelLine.lineLength2 : pos2.x + labelLine.lineLength2;
|
||||
var pos5 = new Vector3(pos5X, pos2.y);
|
||||
switch (labelLine.lineType)
|
||||
{
|
||||
case LabelLine.LineType.BrokenLine:
|
||||
UGL.DrawLine(vh, pos1, pos2, pos5, labelLine.lineWidth, color);
|
||||
break;
|
||||
case LabelLine.LineType.Curves:
|
||||
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, labelLine.lineWidth, color,
|
||||
chart.settings.lineSmoothness);
|
||||
break;
|
||||
case LabelLine.LineType.HorizontalLine:
|
||||
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
|
||||
UGL.DrawLine(vh, pos6, pos4, labelLine.lineWidth, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPieLabel(Serie serie, int dataIndex, SerieData serieData, Color serieColor)
|
||||
{
|
||||
if (serieData.labelObject == null) return;
|
||||
var emphasis = serie.emphasis;
|
||||
var currAngle = serieData.context.halfAngle;
|
||||
var isHighlight = (serieData.context.highlight && emphasis != null && emphasis.label.show);
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||
var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
|
||||
var showLabel = ((serieLabel.show || isHighlight) && serieData.context.canShowLabel);
|
||||
if (showLabel)
|
||||
{
|
||||
serieData.SetLabelActive(showLabel);
|
||||
float rotate = 0;
|
||||
bool isInsidePosition = serieLabel.position == LabelStyle.Position.Inside;
|
||||
if (serieLabel.textStyle.rotate > 0 && isInsidePosition)
|
||||
{
|
||||
if (currAngle > 180) rotate += 270 - currAngle;
|
||||
else rotate += -(currAngle - 90);
|
||||
}
|
||||
Color color = serieColor;
|
||||
if (isHighlight)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(emphasis.label.textStyle.color))
|
||||
{
|
||||
color = emphasis.label.textStyle.color;
|
||||
}
|
||||
}
|
||||
else if (!ChartHelper.IsClearColor(serieLabel.textStyle.color))
|
||||
{
|
||||
color = serieLabel.textStyle.color;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = isInsidePosition ? Color.white : serieColor;
|
||||
}
|
||||
var fontSize = isHighlight
|
||||
? emphasis.label.textStyle.GetFontSize(chart.theme.common)
|
||||
: serieLabel.textStyle.GetFontSize(chart.theme.common);
|
||||
var fontStyle = isHighlight
|
||||
? emphasis.label.textStyle.fontStyle
|
||||
: serieLabel.textStyle.fontStyle;
|
||||
|
||||
serieData.labelObject.label.SetColor(color);
|
||||
serieData.labelObject.label.SetFontSize(fontSize);
|
||||
serieData.labelObject.label.SetFontStyle(fontStyle);
|
||||
serieData.labelObject.SetLabelRotate(rotate);
|
||||
if (!string.IsNullOrEmpty(serieLabel.formatter))
|
||||
{
|
||||
var value = serieData.data[1];
|
||||
var total = serie.yTotal;
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
|
||||
serieLabel, serieColor);
|
||||
if (serieData.labelObject.SetText(content)) chart.RefreshPainter(serie);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serieData.labelObject.SetText(serieData.name)) chart.RefreshPainter(serie);
|
||||
}
|
||||
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel, labelLine));
|
||||
if (showLabel) serieData.labelObject.SetLabelPosition(serieLabel.offset);
|
||||
else serieData.SetLabelActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
serieData.labelObject.UpdateIcon(iconStyle);
|
||||
}
|
||||
|
||||
private int GetPiePosIndex(Serie serie, Vector2 local)
|
||||
{
|
||||
if (!(serie is Pie)) return -1;
|
||||
var dist = Vector2.Distance(local, serie.context.center);
|
||||
var maxRadius = serie.context.outsideRadius + 3 * chart.theme.serie.pieSelectedOffset;
|
||||
if (dist < serie.context.insideRadius || dist > maxRadius) return -1;
|
||||
Vector2 dir = local - new Vector2(serie.context.center.x, serie.context.center.y);
|
||||
float angle = ChartHelper.GetAngle360(Vector2.up, dir);
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
if (angle >= serieData.context.startAngle && angle <= serieData.context.toAngle)
|
||||
{
|
||||
var ndist = !serieData.selected ? dist :
|
||||
Vector2.Distance(local, serieData.context.offsetCenter);
|
||||
if (ndist >= serieData.context.insideRadius && ndist <= serieData.context.outsideRadius)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private bool PointerIsInPieSerie(Serie serie, Vector2 local)
|
||||
{
|
||||
if (!(serie is Pie)) return false;
|
||||
var dist = Vector2.Distance(local, serie.context.center);
|
||||
if (dist >= serie.context.insideRadius && dist <= serie.context.outsideRadius) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Pie/PieHandler.cs.meta
Normal file
11
Runtime/Serie/Pie/PieHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13b8c981e5910447fbe769d539b77f96
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Radar.meta
Normal file
8
Runtime/Serie/Radar.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 375cebcd4f8c54025ab608f35b1fa8c6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
32
Runtime/Serie/Radar/Radar.cs
Normal file
32
Runtime/Serie/Radar/Radar.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(RadarHandler), true)]
|
||||
[RequireChartComponent(typeof(RadarCoord))]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(LabelLine), typeof(AreaStyle), typeof(Emphasis))]
|
||||
public class Radar : Serie, INeedSerieContainer
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
|
||||
public override bool useDataNameForColor { get { return true; } }
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
chart.AddChartComponentWhenNoExist<RadarCoord>();
|
||||
var serie = chart.AddSerie<Radar>(serieName);
|
||||
serie.symbol.show = true;
|
||||
serie.symbol.type = SymbolType.Circle;
|
||||
serie.showDataName = true;
|
||||
List<double> data = new List<double>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
data.Add(Random.Range(20, 90));
|
||||
}
|
||||
chart.AddData(serie.index, data, "legendName");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Radar/Radar.cs.meta
Normal file
11
Runtime/Serie/Radar/Radar.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bda9968e18724e389ff1cbde57baeee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
520
Runtime/Serie/Radar/RadarHandler.cs
Normal file
520
Runtime/Serie/Radar/RadarHandler.cs
Normal file
@@ -0,0 +1,520 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class RadarHandler : SerieHandler<Radar>
|
||||
{
|
||||
private RadarCoord m_RadarCoord;
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
switch (serie.radarType)
|
||||
{
|
||||
case RadarType.Multiple:
|
||||
DrawMutipleRadar(vh);
|
||||
break;
|
||||
case RadarType.Single:
|
||||
DrawSingleRadar(vh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
if (!serie.context.pointerEnter)
|
||||
return;
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
if (serie.radarType == RadarType.Single)
|
||||
{
|
||||
UpdateItemSerieParams(ref paramList, ref title, dataIndex, category,
|
||||
marker, itemFormatter, numericFormatter);
|
||||
return;
|
||||
}
|
||||
|
||||
var radar = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
|
||||
if (radar == null)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
var color = chart.theme.GetColor(dataIndex);
|
||||
title = serieData.name;
|
||||
for (int i = 0; i < serieData.data.Count; i++)
|
||||
{
|
||||
var indicator = radar.GetIndicator(i);
|
||||
|
||||
var param = new SerieParams();
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.dimension = i;
|
||||
param.serieData = serieData;
|
||||
param.value = serieData.GetData(i);
|
||||
param.total = indicator.max;
|
||||
param.color = color;
|
||||
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(indicator == null ? string.Empty : indicator.name);
|
||||
param.columns.Add(ChartCached.NumberToStr(serieData.GetData(i), param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RefreshLabelInternal()
|
||||
{
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.GetSerie(i);
|
||||
if (!(serie is Radar)) continue;
|
||||
if (!serie.show && serie.radarType != RadarType.Single) continue;
|
||||
var radar = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
|
||||
if (radar == null) continue;
|
||||
var center = radar.context.center;
|
||||
for (int n = 0; n < serie.dataCount; n++)
|
||||
{
|
||||
var serieData = serie.data[n];
|
||||
if (serieData.labelObject == null) continue;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
|
||||
var labelPos = serieData.context.labelPosition;
|
||||
if (serieLabel.margin != 0)
|
||||
{
|
||||
labelPos += serieLabel.margin * (labelPos - center).normalized;
|
||||
}
|
||||
serieData.labelObject.SetPosition(labelPos);
|
||||
serieData.labelObject.UpdateIcon(iconStyle);
|
||||
if (serie.show && serieLabel.show && serieData.context.canShowLabel)
|
||||
{
|
||||
var value = serieData.GetCurrData(1);
|
||||
var max = radar.GetIndicatorMax(n);
|
||||
SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, chart.theme);
|
||||
serieData.SetLabelActive(serieData.context.labelPosition != Vector3.zero);
|
||||
serieData.labelObject.SetLabelPosition(serieLabel.offset);
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, max,
|
||||
serieLabel, Color.clear);
|
||||
if (serieData.labelObject.SetText(content))
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataShow(serie, legendName, show);
|
||||
chart.UpdateLegendColor(legendName, show);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataHighlighted(serie, legendName, true);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataHighlighted(serie, legendName, false);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
var needCheck = m_LegendEnter || (chart.isPointerInChart && m_RadarCoord.IsPointerEnter());
|
||||
var needInteract = false;
|
||||
var needHideAll = false;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag == needCheck)
|
||||
return;
|
||||
needHideAll = true;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerEnter = false;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
switch (serie.radarType)
|
||||
{
|
||||
case RadarType.Multiple:
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
serieData.index = i;
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
if (needHideAll || m_LegendEnter)
|
||||
{
|
||||
serieData.context.highlight = needHideAll ? false : true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize, serieData.context.highlight);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
foreach (var pos in serieData.context.dataPoints)
|
||||
{
|
||||
if (Vector3.Distance(chart.pointerPos, pos) < symbolSize * 2)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
serie.context.pointerItemDataIndex = i;
|
||||
serieData.context.highlight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize, serieData.context.highlight);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RadarType.Single:
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
serieData.index = i;
|
||||
if (Vector3.Distance(chart.pointerPos, serieData.context.position) < serie.symbol.size * 2)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
serie.context.pointerItemDataIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMutipleRadar(VertexHelper vh)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
m_RadarCoord = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
|
||||
if (m_RadarCoord == null) return;
|
||||
|
||||
serie.containerIndex = m_RadarCoord.index;
|
||||
serie.containterInstanceId = m_RadarCoord.instanceId;
|
||||
|
||||
var areaStyle = serie.areaStyle;
|
||||
|
||||
var startPoint = Vector3.zero;
|
||||
var toPoint = Vector3.zero;
|
||||
var firstPoint = Vector3.zero;
|
||||
var indicatorNum = m_RadarCoord.indicatorList.Count;
|
||||
var angle = 2 * Mathf.PI / indicatorNum;
|
||||
var centerPos = m_RadarCoord.context.center;
|
||||
serie.animation.InitProgress(0, 1);
|
||||
if (!serie.show || serie.animation.HasFadeOut())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChanging = false;
|
||||
var interacting = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
SerieHelper.GetAllMinMaxData(serie, m_RadarCoord.ceilRate);
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
string dataName = serieData.name;
|
||||
if (!serieData.show)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var isHighlight = serieData.context.highlight;
|
||||
var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, j, isHighlight);
|
||||
var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, j, isHighlight);
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, j, isHighlight);
|
||||
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
int dataCount = m_RadarCoord.indicatorList.Count;
|
||||
serieData.context.dataPoints.Clear();
|
||||
for (int n = 0; n < dataCount; n++)
|
||||
{
|
||||
if (n >= serieData.data.Count) break;
|
||||
var max = m_RadarCoord.GetIndicatorMax(n);
|
||||
var value = serieData.GetCurrData(n, dataChangeDuration);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
if (max == 0)
|
||||
{
|
||||
max = serie.context.dataMax;
|
||||
}
|
||||
var radius = (float)(max < 0 ? m_RadarCoord.context.dataRadius - m_RadarCoord.context.dataRadius * value / max
|
||||
: m_RadarCoord.context.dataRadius * value / max);
|
||||
var currAngle = (n + (m_RadarCoord.positionType == RadarCoord.PositionType.Between ? 0.5f : 0)) * angle;
|
||||
radius *= rate;
|
||||
if (n == 0)
|
||||
{
|
||||
startPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
|
||||
centerPos.y + radius * Mathf.Cos(currAngle));
|
||||
firstPoint = startPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
toPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
|
||||
centerPos.y + radius * Mathf.Cos(currAngle));
|
||||
if (areaStyle != null && areaStyle.show)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
|
||||
}
|
||||
startPoint = toPoint;
|
||||
}
|
||||
serieData.context.dataPoints.Add(startPoint);
|
||||
}
|
||||
if (areaStyle != null && areaStyle.show)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
|
||||
}
|
||||
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
|
||||
{
|
||||
for (int m = 0; m < serieData.context.dataPoints.Count; m++)
|
||||
{
|
||||
var point = serieData.context.dataPoints[m];
|
||||
var symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(null, chart.theme.serie.lineSymbolSelectedSize)
|
||||
: serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize);
|
||||
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
|
||||
{
|
||||
symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(serieData.data, symbolSize)
|
||||
: serie.symbol.GetSize(serieData.data, symbolSize);
|
||||
serieData.interact.SetValue(ref interacting, symbolSize);
|
||||
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
|
||||
}
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, j, isHighlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, j, isHighlight);
|
||||
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, j, isHighlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
|
||||
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
|
||||
symbolToColor, symbolEmptyColor, serie.symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging || interacting)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSingleRadar(VertexHelper vh)
|
||||
{
|
||||
var radar = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
|
||||
if (radar == null)
|
||||
return;
|
||||
|
||||
var indicatorNum = radar.indicatorList.Count;
|
||||
var angle = 2 * Mathf.PI / indicatorNum;
|
||||
var centerPos = radar.context.center;
|
||||
serie.animation.InitProgress(0, 1);
|
||||
serie.context.dataPoints.Clear();
|
||||
if (!serie.show || serie.animation.HasFadeOut())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var startPoint = Vector3.zero;
|
||||
var toPoint = Vector3.zero;
|
||||
var firstPoint = Vector3.zero;
|
||||
var lastColor = ColorUtil.clearColor32;
|
||||
var firstColor = ColorUtil.clearColor32;
|
||||
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChanging = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var startIndex = GetStartShowIndex(serie);
|
||||
var endIndex = GetEndShowIndex(serie);
|
||||
SerieHelper.UpdateMinMaxData(serie, 1, radar.ceilRate);
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
serieData.index = j;
|
||||
string dataName = serieData.name;
|
||||
|
||||
if (!serieData.show)
|
||||
{
|
||||
serieData.context.labelPosition = Vector3.zero;
|
||||
continue;
|
||||
}
|
||||
var isHighlight = serie.context.pointerEnter;
|
||||
var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, j, isHighlight);
|
||||
var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, j, isHighlight);
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, j, isHighlight);
|
||||
int dataCount = radar.indicatorList.Count;
|
||||
var index = serieData.index;
|
||||
var p = radar.context.center;
|
||||
var max = radar.GetIndicatorMax(index);
|
||||
var value = serieData.GetCurrData(1, dataChangeDuration);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
if (max == 0)
|
||||
{
|
||||
max = serie.context.dataMax;
|
||||
}
|
||||
if (!radar.IsInIndicatorRange(j, serieData.GetData(1)))
|
||||
{
|
||||
lineColor = radar.outRangeColor;
|
||||
}
|
||||
var radius = (float)(max < 0 ? radar.context.dataRadius - radar.context.dataRadius * value / max
|
||||
: radar.context.dataRadius * value / max);
|
||||
var currAngle = (index + (radar.positionType == RadarCoord.PositionType.Between ? 0.5f : 0)) * angle;
|
||||
radius *= rate;
|
||||
if (index == startIndex)
|
||||
{
|
||||
startPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
|
||||
p.y + radius * Mathf.Cos(currAngle));
|
||||
firstPoint = startPoint;
|
||||
lastColor = lineColor;
|
||||
firstColor = lineColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
|
||||
p.y + radius * Mathf.Cos(currAngle));
|
||||
if (serie.areaStyle.show)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show)
|
||||
{
|
||||
if (radar.connectCenter)
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, centerPos,
|
||||
chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor);
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, toPoint, chart.theme.serie.lineWidth,
|
||||
LineStyle.Type.Solid, radar.lineGradient ? lastColor : lineColor, lineColor);
|
||||
}
|
||||
startPoint = toPoint;
|
||||
lastColor = lineColor;
|
||||
}
|
||||
serieData.context.position = startPoint;
|
||||
serieData.context.labelPosition = startPoint;
|
||||
|
||||
if (serie.areaStyle.show && j == endIndex)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show && j == endIndex)
|
||||
{
|
||||
if (radar.connectCenter)
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, centerPos,
|
||||
chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor);
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, firstPoint, chart.theme.serie.lineWidth,
|
||||
LineStyle.Type.Solid, lineColor, radar.lineGradient ? firstColor : lineColor);
|
||||
}
|
||||
}
|
||||
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
|
||||
{
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
if (!serieData.show) continue;
|
||||
var isHighlight = serie.highlight || serieData.context.highlight || serie.context.pointerEnter;
|
||||
var serieIndex = serieData.index;
|
||||
var symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize)
|
||||
: serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
|
||||
if (!radar.IsInIndicatorRange(j, serieData.GetData(1)))
|
||||
{
|
||||
symbolColor = radar.outRangeColor;
|
||||
symbolToColor = radar.outRangeColor;
|
||||
}
|
||||
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, serieData.context.labelPosition, symbolColor,
|
||||
symbolToColor, symbolEmptyColor, serie.symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetStartShowIndex(Serie serie)
|
||||
{
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
if (serie.data[i].show) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
private int GetEndShowIndex(Serie serie)
|
||||
{
|
||||
for (int i = serie.dataCount - 1; i >= 0; i--)
|
||||
{
|
||||
if (serie.data[i].show) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void DrawRadarSymbol(VertexHelper vh, Serie serie, SerieData serieData, int serieIndex, bool isHighlight,
|
||||
List<Vector3> pointList)
|
||||
{
|
||||
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
|
||||
{
|
||||
var symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize)
|
||||
: serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
|
||||
foreach (var point in pointList)
|
||||
{
|
||||
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
|
||||
symbolToColor, symbolEmptyColor, serie.symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Radar/RadarHandler.cs.meta
Normal file
11
Runtime/Serie/Radar/RadarHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8dd73709db7a4451b2fe6f03476cb7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Ring.meta
Normal file
8
Runtime/Serie/Ring.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c15a1b60f1d3c4daca1fcd88d96ae7e7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
29
Runtime/Serie/Ring/Ring.cs
Normal file
29
Runtime/Serie/Ring/Ring.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(RingHandler), true)]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(Emphasis))]
|
||||
public class Ring : Serie
|
||||
{
|
||||
public override bool useDataNameForColor { get { return true; } }
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Ring>(serieName);
|
||||
serie.roundCap = true;
|
||||
serie.radius = new float[] { 0.3f, 0.35f };
|
||||
serie.titleStyle.show = false;
|
||||
serie.titleStyle.textStyle.offset = new Vector2(0, 30);
|
||||
serie.AddExtraComponent<LabelStyle>();
|
||||
serie.label.show = true;
|
||||
serie.label.position = LabelStyle.Position.Center;
|
||||
serie.label.formatter = "{d:f0}%";
|
||||
serie.label.textStyle.fontSize = 28;
|
||||
var value = Random.Range(30, 90);
|
||||
var max = 100;
|
||||
chart.AddData(serie.index, value, max, "data1");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Ring/Ring.cs.meta
Normal file
11
Runtime/Serie/Ring/Ring.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c7fe8316f26241d8a9f4b3ce94d61bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
322
Runtime/Serie/Ring/RingHandler.cs
Normal file
322
Runtime/Serie/Ring/RingHandler.cs
Normal file
@@ -0,0 +1,322 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class RingHandler : SerieHandler<Ring>
|
||||
{
|
||||
private bool m_UpdateTitleText = false;
|
||||
private bool m_UpdateLabelText = false;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (m_UpdateTitleText)
|
||||
{
|
||||
m_UpdateTitleText = false;
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie is Ring)
|
||||
{
|
||||
serie.titleStyle.SetText(serie.serieName);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_UpdateLabelText)
|
||||
{
|
||||
m_UpdateLabelText = false;
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie is Ring)
|
||||
{
|
||||
SerieLabelHelper.SetRingLabelText(serie, chart.theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var ringIndex = GetRingIndex(chart.pointerPos);
|
||||
if (ringIndex >= 0)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
serie.context.pointerItemDataIndex = ringIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerEnter = false;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
if (dataIndex < 0)
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.category = category;
|
||||
param.dimension = 0;
|
||||
param.serieData = serieData;
|
||||
param.value = serieData.GetData(0);
|
||||
param.total = serieData.GetData(1);
|
||||
param.color = chart.theme.GetColor(dataIndex);
|
||||
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter); ;
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(serieData.name);
|
||||
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
if (!serie.show || serie.animation.HasFadeOut()) return;
|
||||
var data = serie.data;
|
||||
serie.animation.InitProgress(serie.startAngle, serie.startAngle + 360);
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var ringWidth = serie.context.outsideRadius - serie.context.insideRadius;
|
||||
var dataChanging = false;
|
||||
for (int j = 0; j < data.Count; j++)
|
||||
{
|
||||
var serieData = data[j];
|
||||
if (!serieData.show) continue;
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
var value = serieData.GetFirstData(dataChangeDuration);
|
||||
var max = serieData.GetLastData();
|
||||
var degree = (float)(360 * value / max);
|
||||
var startDegree = GetStartAngle(serie);
|
||||
var toDegree = GetToAngle(serie, degree);
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.context.highlight);
|
||||
var itemColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, j, serieData.context.highlight);
|
||||
var itemToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, j, serieData.context.highlight);
|
||||
var outsideRadius = serie.context.outsideRadius - j * (ringWidth + serie.ringGap);
|
||||
var insideRadius = outsideRadius - ringWidth;
|
||||
var centerRadius = (outsideRadius + insideRadius) / 2;
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var roundCap = serie.roundCap && insideRadius > 0;
|
||||
|
||||
serieData.context.startAngle = serie.clockwise ? startDegree : toDegree;
|
||||
serieData.context.toAngle = serie.clockwise ? toDegree : startDegree;
|
||||
serieData.context.insideRadius = insideRadius;
|
||||
serieData.context.outsideRadius = serieData.radius > 0 ? serieData.radius : outsideRadius;
|
||||
if (itemStyle.backgroundColor.a != 0)
|
||||
{
|
||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius, outsideRadius, itemStyle.backgroundColor,
|
||||
itemStyle.backgroundColor, Color.clear, 0, 360, borderWidth, borderColor, 0,
|
||||
chart.settings.cicleSmoothness, false, serie.clockwise);
|
||||
}
|
||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius, outsideRadius, itemColor, itemToColor,
|
||||
Color.clear, startDegree, toDegree, borderWidth, borderColor, 0, chart.settings.cicleSmoothness,
|
||||
roundCap, serie.clockwise);
|
||||
DrawCenter(vh, serie, serieData, insideRadius, j == data.Count - 1);
|
||||
UpateLabelPosition(serie, serieData, j, startDegree, toDegree, centerRadius);
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(360);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshChart();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataShow(serie, legendName, show);
|
||||
chart.UpdateLegendColor(legendName, show);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataHighlighted(serie, legendName, true);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (!serie.IsLegendName(legendName))
|
||||
return;
|
||||
LegendHelper.CheckDataHighlighted(serie, legendName, false);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
|
||||
public override void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
private float GetStartAngle(Serie serie)
|
||||
{
|
||||
return serie.clockwise ? serie.startAngle : 360 - serie.startAngle;
|
||||
}
|
||||
|
||||
private float GetToAngle(Serie serie, float angle)
|
||||
{
|
||||
var toAngle = angle + serie.startAngle;
|
||||
if (!serie.clockwise)
|
||||
{
|
||||
toAngle = 360 - angle - serie.startAngle;
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
var currAngle = serie.animation.GetCurrDetail();
|
||||
if (serie.clockwise)
|
||||
{
|
||||
toAngle = toAngle > currAngle ? currAngle : toAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
toAngle = toAngle < 360 - currAngle ? 360 - currAngle : toAngle;
|
||||
}
|
||||
}
|
||||
return toAngle;
|
||||
}
|
||||
|
||||
private void DrawCenter(VertexHelper vh, Serie serie, SerieData serieData, float insideRadius, bool last)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.centerColor) && last)
|
||||
{
|
||||
var radius = insideRadius - itemStyle.centerGap;
|
||||
var smoothness = chart.settings.cicleSmoothness;
|
||||
UGL.DrawCricle(vh, serie.context.center, radius, itemStyle.centerColor, smoothness);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpateLabelPosition(Serie serie, SerieData serieData, int index, float startAngle,
|
||||
float toAngle, float centerRadius)
|
||||
{
|
||||
var label = serie.label;
|
||||
if (label == null || !label.show) return;
|
||||
if (serieData.labelObject == null) return;
|
||||
switch (label.position)
|
||||
{
|
||||
case LabelStyle.Position.Center:
|
||||
serieData.context.labelPosition = serie.context.center + label.offset;
|
||||
break;
|
||||
case LabelStyle.Position.Bottom:
|
||||
var px1 = Mathf.Sin(startAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
var py1 = Mathf.Cos(startAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
var xDiff = serie.clockwise ? -label.margin : label.margin;
|
||||
serieData.context.labelPosition = serie.context.center + new Vector3(px1 + xDiff, py1);
|
||||
break;
|
||||
case LabelStyle.Position.Top:
|
||||
startAngle += serie.clockwise ? -label.margin : label.margin;
|
||||
toAngle += serie.clockwise ? label.margin : -label.margin;
|
||||
var px2 = Mathf.Sin(toAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
var py2 = Mathf.Cos(toAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
serieData.context.labelPosition = serie.context.center + new Vector3(px2, py2);
|
||||
break;
|
||||
}
|
||||
serieData.labelObject.SetLabelPosition(serieData.context.labelPosition);
|
||||
}
|
||||
|
||||
private void DrawBackground(VertexHelper vh, Serie serie, SerieData serieData, int index, float insideRadius, float outsideRadius)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, index, false);
|
||||
if (itemStyle.backgroundWidth != 0)
|
||||
{
|
||||
var centerRadius = (outsideRadius + insideRadius) / 2;
|
||||
var inradius = centerRadius - itemStyle.backgroundWidth / 2;
|
||||
var outradius = centerRadius + itemStyle.backgroundWidth / 2;
|
||||
UGL.DrawDoughnut(vh, serie.context.center, inradius,
|
||||
outradius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius,
|
||||
outsideRadius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBorder(VertexHelper vh, Serie serie, SerieData serieData, float insideRadius, float outsideRadius)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (itemStyle.show && itemStyle.borderWidth > 0 && !ChartHelper.IsClearColor(itemStyle.borderColor))
|
||||
{
|
||||
UGL.DrawDoughnut(vh, serie.context.center, outsideRadius,
|
||||
outsideRadius + itemStyle.borderWidth, itemStyle.borderColor,
|
||||
Color.clear, chart.settings.cicleSmoothness);
|
||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius,
|
||||
insideRadius + itemStyle.borderWidth, itemStyle.borderColor,
|
||||
Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DrawRoundCap(VertexHelper vh, Serie serie, Vector3 centerPos, Color color,
|
||||
float insideRadius, float outsideRadius, ref float drawStartDegree, ref float drawEndDegree)
|
||||
{
|
||||
if (serie.roundCap && insideRadius > 0 && drawStartDegree != drawEndDegree)
|
||||
{
|
||||
var width = (outsideRadius - insideRadius) / 2;
|
||||
var radius = insideRadius + width;
|
||||
|
||||
var diffDegree = Mathf.Asin(width / radius) * Mathf.Rad2Deg;
|
||||
drawStartDegree += serie.clockwise ? diffDegree : -diffDegree;
|
||||
drawEndDegree -= serie.clockwise ? diffDegree : -diffDegree;
|
||||
UGL.DrawRoundCap(vh, centerPos, width, radius, drawStartDegree, serie.clockwise, color, false);
|
||||
UGL.DrawRoundCap(vh, centerPos, width, radius, drawEndDegree, serie.clockwise, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetRingIndex(Vector2 local)
|
||||
{
|
||||
var dist = Vector2.Distance(local, serie.context.center);
|
||||
if (dist > serie.context.outsideRadius) return -1;
|
||||
Vector2 dir = local - new Vector2(serie.context.center.x, serie.context.center.y);
|
||||
float angle = VectorAngle(Vector2.up, dir);
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
if (dist >= serieData.context.insideRadius &&
|
||||
dist <= serieData.context.outsideRadius &&
|
||||
angle >= serieData.context.startAngle &&
|
||||
angle <= serieData.context.toAngle)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private float VectorAngle(Vector2 from, Vector2 to)
|
||||
{
|
||||
float angle;
|
||||
|
||||
Vector3 cross = Vector3.Cross(from, to);
|
||||
angle = Vector2.Angle(from, to);
|
||||
angle = cross.z > 0 ? -angle : angle;
|
||||
angle = (angle + 360) % 360;
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Ring/RingHandler.cs.meta
Normal file
11
Runtime/Serie/Ring/RingHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c3c486efd6d8464a88d8f4b572b7bc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Scatter.meta
Normal file
8
Runtime/Serie/Scatter.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97fc5bddab1db4321aa7377ab8b8b8bc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Runtime/Serie/Scatter/BaseScatter.cs
Normal file
10
Runtime/Serie/Scatter/BaseScatter.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
public class BaseScatter : Serie, INeedSerieContainer
|
||||
{
|
||||
public int containerIndex { get; internal set; }
|
||||
public int containterInstanceId { get; internal set; }
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Scatter/BaseScatter.cs.meta
Normal file
11
Runtime/Serie/Scatter/BaseScatter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dba0ca827ad4d4b9989def35aba66665
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
347
Runtime/Serie/Scatter/BaseScatterHandler.cs
Normal file
347
Runtime/Serie/Scatter/BaseScatterHandler.cs
Normal file
@@ -0,0 +1,347 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal class BaseScatterHandler<T> : SerieHandler<T> where T : BaseScatter
|
||||
{
|
||||
private GridCoord m_Grid;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
UpdateSerieContext();
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
string marker, string itemFormatter, string numericFormatter,
|
||||
ref List<SerieParams> paramList, ref string title)
|
||||
{
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
title = serie.serieName;
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.category = category;
|
||||
param.dimension = 1;
|
||||
param.serieData = serieData;
|
||||
param.color = chart.theme.GetColor(serie.index);
|
||||
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
if (!string.IsNullOrEmpty(serieData.name))
|
||||
param.columns.Add(serieData.name);
|
||||
param.columns.Add(ChartCached.NumberToStr(serieData.GetData(1), param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
{
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
|
||||
if (serie.IsUseCoord<SingleAxisCoord>())
|
||||
{
|
||||
DrawSingAxisScatterSerie(vh, colorIndex, serie);
|
||||
}
|
||||
else if (serie.IsUseCoord<GridCoord>())
|
||||
{
|
||||
DrawScatterSerie(vh, colorIndex, serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSerieContext()
|
||||
{
|
||||
var needCheck = m_LegendEnter || (chart.isPointerInChart && (m_Grid == null || m_Grid.IsPointerEnter()));
|
||||
|
||||
var needHideAll = false;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag == needCheck)
|
||||
return;
|
||||
needHideAll = true;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
var themeSymbolSize = chart.theme.serie.scatterSymbolSize;
|
||||
var themeSymbolSelectedSize = chart.theme.serie.scatterSymbolSelectedSize;
|
||||
var needInteract = false;
|
||||
for (int i = serie.dataCount - 1; i >= 0; i--)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
|
||||
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
|
||||
if (m_LegendEnter ||
|
||||
(!needHideAll && Vector3.Distance(serieData.context.position, chart.pointerPos) <= symbolSize))
|
||||
{
|
||||
serie.context.pointerItemDataIndex = i;
|
||||
serie.context.pointerEnter = true;
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needInteract, symbolSize);
|
||||
}
|
||||
}
|
||||
if (needInteract)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawScatterSerie(VertexHelper vh, int colorIndex, BaseScatter serie)
|
||||
{
|
||||
if (serie.animation.HasFadeOut())
|
||||
return;
|
||||
|
||||
if (!serie.show)
|
||||
return;
|
||||
|
||||
XAxis xAxis;
|
||||
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex))
|
||||
return;
|
||||
|
||||
YAxis yAxis;
|
||||
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex))
|
||||
return;
|
||||
|
||||
if (!chart.TryGetChartComponent<GridCoord>(out m_Grid, xAxis.gridIndex))
|
||||
return;
|
||||
|
||||
DataZoom xDataZoom;
|
||||
DataZoom yDataZoom;
|
||||
chart.GetDataZoomOfSerie(serie, out xDataZoom, out yDataZoom);
|
||||
|
||||
var theme = chart.theme;
|
||||
int maxCount = serie.maxShow > 0 ?
|
||||
(serie.maxShow > serie.dataCount ? serie.dataCount : serie.maxShow)
|
||||
: serie.dataCount;
|
||||
serie.animation.InitProgress(0, 1);
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var dataChanging = false;
|
||||
var interacting = false;
|
||||
var dataList = serie.GetDataList(xDataZoom);
|
||||
var isEffectScatter = serie is EffectScatter;
|
||||
|
||||
serie.containerIndex = m_Grid.index;
|
||||
serie.containterInstanceId = m_Grid.instanceId;
|
||||
|
||||
foreach (var serieData in dataList)
|
||||
{
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
if (!symbol.ShowSymbol(serieData.index, maxCount))
|
||||
continue;
|
||||
|
||||
var highlight = serie.highlight || serieData.context.highlight;
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, theme, colorIndex, highlight);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, theme, colorIndex, highlight);
|
||||
var emptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, theme, colorIndex, highlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, theme, highlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
|
||||
double xValue = serieData.GetCurrData(0, dataChangeDuration, xAxis.inverse);
|
||||
double yValue = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse);
|
||||
|
||||
if (serieData.IsDataChanged())
|
||||
dataChanging = true;
|
||||
|
||||
float pX = m_Grid.context.x + xAxis.axisLine.GetWidth(theme.axis.lineWidth);
|
||||
float pY = m_Grid.context.y + yAxis.axisLine.GetWidth(theme.axis.lineWidth);
|
||||
float xDataHig = GetDataHig(xAxis, xValue, m_Grid.context.width);
|
||||
float yDataHig = GetDataHig(yAxis, yValue, m_Grid.context.height);
|
||||
var pos = new Vector3(pX + xDataHig, pY + yDataHig);
|
||||
|
||||
if (!m_Grid.Contains(pos))
|
||||
continue;
|
||||
|
||||
serie.context.dataPoints.Add(pos);
|
||||
serieData.context.position = pos;
|
||||
var datas = serieData.data;
|
||||
var symbolSize = serie.highlight || serieData.context.highlight
|
||||
? theme.serie.scatterSymbolSelectedSize
|
||||
: theme.serie.scatterSymbolSize;
|
||||
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
|
||||
{
|
||||
symbolSize = highlight
|
||||
? symbol.GetSelectedSize(serieData.data, symbolSize)
|
||||
: symbol.GetSize(serieData.data, symbolSize);
|
||||
serieData.interact.SetValue(ref interacting, symbolSize);
|
||||
}
|
||||
|
||||
symbolSize *= rate;
|
||||
|
||||
if (isEffectScatter)
|
||||
{
|
||||
for (int count = 0; count < symbol.animationSize.Count; count++)
|
||||
{
|
||||
var nowSize = symbol.animationSize[count];
|
||||
color.a = (byte)(255 * (symbolSize - nowSize) / symbolSize);
|
||||
chart.DrawSymbol(vh, symbol.type, nowSize, symbolBorder, pos, color, toColor, emptyColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (symbolSize > 100) symbolSize = 100;
|
||||
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, pos, color, toColor, emptyColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging || interacting)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawSingAxisScatterSerie(VertexHelper vh, int colorIndex, BaseScatter serie)
|
||||
{
|
||||
if (serie.animation.HasFadeOut())
|
||||
return;
|
||||
|
||||
if (!serie.show)
|
||||
return;
|
||||
|
||||
var axis = chart.GetChartComponent<SingleAxis>(serie.singleAxisIndex);
|
||||
if (axis == null)
|
||||
return;
|
||||
|
||||
DataZoom xDataZoom;
|
||||
DataZoom yDataZoom;
|
||||
chart.GetDataZoomOfSerie(serie, out xDataZoom, out yDataZoom);
|
||||
|
||||
var theme = chart.theme;
|
||||
int maxCount = serie.maxShow > 0 ?
|
||||
(serie.maxShow > serie.dataCount ? serie.dataCount : serie.maxShow)
|
||||
: serie.dataCount;
|
||||
serie.animation.InitProgress(0, 1);
|
||||
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var dataChanging = false;
|
||||
var dataList = serie.GetDataList(xDataZoom);
|
||||
var isEffectScatter = serie is EffectScatter;
|
||||
|
||||
serie.containerIndex = axis.index;
|
||||
serie.containterInstanceId = axis.instanceId;
|
||||
|
||||
foreach (var serieData in dataList)
|
||||
{
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
if (!symbol.ShowSymbol(serieData.index, maxCount))
|
||||
continue;
|
||||
|
||||
var highlight = serie.highlight || serieData.context.highlight;
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, theme, colorIndex, highlight);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, theme, colorIndex, highlight);
|
||||
var emptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, theme, colorIndex, highlight, false);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, theme, highlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
|
||||
var xValue = serieData.GetCurrData(0, dataChangeDuration, axis.inverse);
|
||||
|
||||
if (serieData.IsDataChanged())
|
||||
dataChanging = true;
|
||||
|
||||
var pos = Vector3.zero;
|
||||
if (axis.orient == Orient.Horizonal)
|
||||
{
|
||||
var xDataHig = GetDataHig(axis, xValue, axis.context.width);
|
||||
var yDataHig = axis.context.height / 2;
|
||||
pos = new Vector3(axis.context.x + xDataHig, axis.context.y + yDataHig);
|
||||
}
|
||||
else
|
||||
{
|
||||
var yDataHig = GetDataHig(axis, xValue, axis.context.width);
|
||||
var xDataHig = axis.context.height / 2;
|
||||
pos = new Vector3(axis.context.x + xDataHig, axis.context.y + yDataHig);
|
||||
}
|
||||
serie.context.dataPoints.Add(pos);
|
||||
serieData.context.position = pos;
|
||||
|
||||
var datas = serieData.data;
|
||||
var symbolSize = 0f;
|
||||
if (serie.highlight || serieData.context.highlight)
|
||||
symbolSize = symbol.GetSelectedSize(datas, theme.serie.scatterSymbolSelectedSize);
|
||||
else
|
||||
symbolSize = symbol.GetSize(datas, theme.serie.scatterSymbolSize);
|
||||
symbolSize *= rate;
|
||||
|
||||
if (isEffectScatter)
|
||||
{
|
||||
if (symbolSize > 100) symbolSize = 100;
|
||||
for (int count = 0; count < symbol.animationSize.Count; count++)
|
||||
{
|
||||
var nowSize = symbol.animationSize[count];
|
||||
color.a = (byte)(255 * (symbolSize - nowSize) / symbolSize);
|
||||
chart.DrawSymbol(vh, symbol.type, nowSize, symbolBorder, pos,
|
||||
color, toColor, emptyColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (symbolSize > 100) symbolSize = 100;
|
||||
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
|
||||
color, toColor, emptyColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private static float GetDataHig(Axis axis, double value, float totalWidth)
|
||||
{
|
||||
if (axis.IsLog())
|
||||
{
|
||||
int minIndex = axis.GetLogMinIndex();
|
||||
float nowIndex = axis.GetLogValue(value);
|
||||
return (nowIndex - minIndex) / axis.splitNumber * totalWidth;
|
||||
}
|
||||
else if (axis.IsCategory())
|
||||
{
|
||||
if (axis.boundaryGap)
|
||||
{
|
||||
float tick = (float)(totalWidth / (axis.context.minMaxRange + 1));
|
||||
return tick / 2 + (float)(value - axis.context.minValue) * tick;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (float)((value - axis.context.minValue) / axis.context.minMaxRange * totalWidth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (float)((value - axis.context.minValue) / axis.context.minMaxRange * totalWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Scatter/BaseScatterHandler.cs.meta
Normal file
11
Runtime/Serie/Scatter/BaseScatterHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31373c1595ff249188e33330f2eff1ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
25
Runtime/Serie/Scatter/EffectScatter.cs
Normal file
25
Runtime/Serie/Scatter/EffectScatter.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(EffectScatterHandler), true)]
|
||||
[CoordOptions(typeof(GridCoord), typeof(SingleAxisCoord))]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(Emphasis))]
|
||||
public class EffectScatter : BaseScatter
|
||||
{
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<EffectScatter>(serieName);
|
||||
serie.symbol.show = true;
|
||||
serie.symbol.type = SymbolType.Circle;
|
||||
serie.itemStyle.opacity = 0.8f;
|
||||
serie.clip = false;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
chart.AddData(serie.index, Random.Range(10, 100), Random.Range(10, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Scatter/EffectScatter.cs.meta
Normal file
11
Runtime/Serie/Scatter/EffectScatter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c34d4976ef53c48a4b091d52694d8a7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Runtime/Serie/Scatter/EffectScatterHandler.cs
Normal file
26
Runtime/Serie/Scatter/EffectScatterHandler.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class EffectScatterHandler : BaseScatterHandler<EffectScatter>
|
||||
{
|
||||
private float m_EffectScatterSpeed = 15;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
var symbolSize = serie.symbol.GetSize(null, chart.theme.serie.scatterSymbolSize);
|
||||
for (int i = 0; i < serie.symbol.animationSize.Count; ++i)
|
||||
{
|
||||
serie.symbol.animationSize[i] += m_EffectScatterSpeed * Time.deltaTime;
|
||||
if (serie.symbol.animationSize[i] > symbolSize)
|
||||
{
|
||||
serie.symbol.animationSize[i] = i * 5;
|
||||
}
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Scatter/EffectScatterHandler.cs.meta
Normal file
11
Runtime/Serie/Scatter/EffectScatterHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb7c24770dff64d7b857f459de7b2333
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Runtime/Serie/Scatter/Scatter.cs
Normal file
27
Runtime/Serie/Scatter/Scatter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[System.Serializable]
|
||||
[SerieHandler(typeof(ScatterHandler), true)]
|
||||
[CoordOptions(typeof(GridCoord), typeof(SingleAxisCoord))]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(Emphasis))]
|
||||
public class Scatter : BaseScatter
|
||||
{
|
||||
public static void AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Scatter>(serieName);
|
||||
serie.symbol.show = true;
|
||||
serie.symbol.type = SymbolType.Circle;
|
||||
serie.itemStyle.opacity = 0.8f;
|
||||
serie.clip = false;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
chart.AddData(serie.index, Random.Range(10, 100), Random.Range(10, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Scatter/Scatter.cs.meta
Normal file
11
Runtime/Serie/Scatter/Scatter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75a031f5547984317b5659a03d7f5e32
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime/Serie/Scatter/ScatterHandler.cs
Normal file
8
Runtime/Serie/Scatter/ScatterHandler.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class ScatterHandler : BaseScatterHandler<Scatter>
|
||||
{
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Scatter/ScatterHandler.cs.meta
Normal file
11
Runtime/Serie/Scatter/ScatterHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ee7d7a8f04034cd38fd9d43f1a41825
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
139
Runtime/Serie/Serie.ExtraComponent.cs
Normal file
139
Runtime/Serie/Serie.ExtraComponent.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public partial class Serie
|
||||
{
|
||||
public static Dictionary<Type, string> extraComponentFieldNameDict = new Dictionary<Type, string>
|
||||
{
|
||||
{typeof(LabelStyle), "m_Labels"},
|
||||
{typeof(LabelLine), "m_LabelLines"},
|
||||
{typeof(EndLabelStyle), "m_EndLabels"},
|
||||
{typeof(LineArrow), "m_LineArrows"},
|
||||
{typeof(AreaStyle), "m_AreaStyles"},
|
||||
{typeof(IconStyle), "m_IconStyles"},
|
||||
{typeof(Emphasis), "m_Emphases"},
|
||||
};
|
||||
|
||||
[SerializeField] private List<LabelStyle> m_Labels = new List<LabelStyle>();
|
||||
[SerializeField] private List<LabelLine> m_LabelLines = new List<LabelLine>();
|
||||
[SerializeField] private List<EndLabelStyle> m_EndLabels = new List<EndLabelStyle>();
|
||||
[SerializeField] private List<LineArrow> m_LineArrows = new List<LineArrow>();
|
||||
[SerializeField] private List<AreaStyle> m_AreaStyles = new List<AreaStyle>();
|
||||
[SerializeField] private List<IconStyle> m_IconStyles = new List<IconStyle>();
|
||||
[SerializeField] private List<Emphasis> m_Emphases = new List<Emphasis>();
|
||||
|
||||
/// <summary>
|
||||
/// The style of area.
|
||||
/// 区域填充样式。
|
||||
/// </summary>
|
||||
public AreaStyle areaStyle { get { return m_AreaStyles.Count > 0 ? m_AreaStyles[0] : null; } }
|
||||
/// <summary>
|
||||
/// Text label of graphic element,to explain some data information about graphic item like value, name and so on.
|
||||
/// 图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。s
|
||||
/// </summary>
|
||||
public LabelStyle label { get { return m_Labels.Count > 0 ? m_Labels[0] : null; } }
|
||||
public LabelStyle endLabel { get { return m_EndLabels.Count > 0 ? m_EndLabels[0] : null; } }
|
||||
/// <summary>
|
||||
/// The line of label.
|
||||
/// 标签上的视觉引导线。
|
||||
/// </summary>
|
||||
public LabelLine labelLine { get { return m_LabelLines.Count > 0 ? m_LabelLines[0] : null; } }
|
||||
/// <summary>
|
||||
/// The arrow of line.
|
||||
/// 折线图的箭头。
|
||||
/// </summary>
|
||||
public LineArrow lineArrow { get { return m_LineArrows.Count > 0 ? m_LineArrows[0] : null; } }
|
||||
/// <summary>
|
||||
/// 高亮的图形样式和文本标签样式。
|
||||
/// </summary>
|
||||
public Emphasis emphasis { get { return m_Emphases.Count > 0 ? m_Emphases[0] : null; } }
|
||||
/// <summary>
|
||||
/// the icon of data.
|
||||
/// 数据项图标样式。
|
||||
/// </summary>
|
||||
public IconStyle iconStyle { get { return m_IconStyles.Count > 0 ? m_IconStyles[0] : null; } }
|
||||
|
||||
public void RemoveAllExtraComponent()
|
||||
{
|
||||
var serieType = GetType();
|
||||
foreach (var kv in extraComponentFieldNameDict)
|
||||
{
|
||||
ReflectionUtil.InvokeListClear(this, serieType.GetField(kv.Value));
|
||||
}
|
||||
SetAllDirty();
|
||||
}
|
||||
|
||||
public T AddExtraComponent<T>() where T : ChildComponent
|
||||
{
|
||||
return AddExtraComponent(typeof(T)) as T;
|
||||
}
|
||||
|
||||
public ISerieExtraComponent AddExtraComponent(Type type)
|
||||
{
|
||||
if (GetType().IsDefined(typeof(SerieExtraComponentAttribute), false))
|
||||
{
|
||||
var attr = GetType().GetAttribute<SerieExtraComponentAttribute>();
|
||||
if (attr.Contains(type))
|
||||
{
|
||||
var fieldName = string.Empty;
|
||||
if (extraComponentFieldNameDict.TryGetValue(type, out fieldName))
|
||||
{
|
||||
var field = typeof(Serie).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (ReflectionUtil.InvokeListCount(this, field) <= 0)
|
||||
{
|
||||
var extraComponent = Activator.CreateInstance(type) as ISerieExtraComponent;
|
||||
ReflectionUtil.InvokeListAdd(this, field, extraComponent);
|
||||
SetAllDirty();
|
||||
return extraComponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReflectionUtil.InvokeListGet<ISerieExtraComponent>(this, field, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new System.Exception(string.Format("Serie {0} not support extra component: {1}",
|
||||
GetType().Name, type.Name));
|
||||
}
|
||||
|
||||
public void RemoveExtraComponent<T>() where T : ISerieExtraComponent
|
||||
{
|
||||
RemoveExtraComponent(typeof(T));
|
||||
}
|
||||
|
||||
public void RemoveExtraComponent(Type type)
|
||||
{
|
||||
if (GetType().IsDefined(typeof(SerieExtraComponentAttribute), false))
|
||||
{
|
||||
var attr = GetType().GetAttribute<SerieExtraComponentAttribute>();
|
||||
if (attr.Contains(type))
|
||||
{
|
||||
var fieldName = string.Empty;
|
||||
if (extraComponentFieldNameDict.TryGetValue(type, out fieldName))
|
||||
{
|
||||
var field = typeof(Serie).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
ReflectionUtil.InvokeListClear(this, field);
|
||||
SetAllDirty();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new System.Exception(string.Format("Serie {0} not support extra component: {1}",
|
||||
GetType().Name, type.Name));
|
||||
}
|
||||
|
||||
private void RemoveExtraComponentList<T>(List<T> list) where T : ISerieExtraComponent
|
||||
{
|
||||
if (list.Count > 0)
|
||||
{
|
||||
list.Clear();
|
||||
SetAllDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Serie.ExtraComponent.cs.meta
Normal file
11
Runtime/Serie/Serie.ExtraComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c4f3a01039fd4e7fbf771a65ede0069
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1752
Runtime/Serie/Serie.cs
Normal file
1752
Runtime/Serie/Serie.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Runtime/Serie/Serie.cs.meta
Normal file
11
Runtime/Serie/Serie.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa9c09045961a4ea9a34a098f099f2a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
102
Runtime/Serie/SerieContext.cs
Normal file
102
Runtime/Serie/SerieContext.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public struct PointInfo
|
||||
{
|
||||
public Vector3 position;
|
||||
public bool isIgnoreBreak;
|
||||
|
||||
public PointInfo(Vector3 pos, bool ignore)
|
||||
{
|
||||
this.position = pos;
|
||||
this.isIgnoreBreak = ignore;
|
||||
}
|
||||
}
|
||||
[System.Serializable]
|
||||
public class SerieContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 鼠标是否进入serie
|
||||
/// </summary>
|
||||
public bool pointerEnter;
|
||||
/// <summary>
|
||||
/// 鼠标当前指示的数据项索引(单个)
|
||||
/// </summary>
|
||||
public int pointerItemDataIndex = -1;
|
||||
/// <summary>
|
||||
/// 鼠标所在轴线上的数据项索引(可能有多个)
|
||||
/// </summary>
|
||||
public List<int> pointerAxisDataIndexs = new List<int>();
|
||||
public bool isTriggerByAxis = false;
|
||||
|
||||
/// <summary>
|
||||
/// 中心点
|
||||
/// </summary>
|
||||
public Vector3 center { get; internal set; }
|
||||
/// <summary>
|
||||
/// 内半径
|
||||
/// </summary>
|
||||
public float insideRadius { get; internal set; }
|
||||
/// <summary>
|
||||
/// 外半径
|
||||
/// </summary>
|
||||
public float outsideRadius { get; internal set; }
|
||||
/// <summary>
|
||||
/// 最大值
|
||||
/// </summary>
|
||||
public double dataMax { get; internal set; }
|
||||
/// <summary>
|
||||
/// 最小值
|
||||
/// </summary>
|
||||
public double dataMin { get; internal set; }
|
||||
public double checkValue { get; set; }
|
||||
/// <summary>
|
||||
/// 左下角坐标X
|
||||
/// </summary>
|
||||
public float x { get; internal set; }
|
||||
/// <summary>
|
||||
/// 左下角坐标Y
|
||||
/// </summary>
|
||||
public float y { get; internal set; }
|
||||
/// <summary>
|
||||
/// 宽
|
||||
/// </summary>
|
||||
public float width { get; internal set; }
|
||||
/// <summary>
|
||||
/// 高
|
||||
/// </summary>
|
||||
public float height { get; internal set; }
|
||||
/// <summary>
|
||||
/// 矩形区域
|
||||
/// </summary>
|
||||
public Rect rect { get; internal set; }
|
||||
/// <summary>
|
||||
/// 绘制顶点数
|
||||
/// </summary>
|
||||
public int vertCount { get; internal set; }
|
||||
/// <summary>
|
||||
/// 数据对应的位置坐标。
|
||||
/// </summary>
|
||||
public List<Vector3> dataPoints = new List<Vector3>();
|
||||
/// <summary>
|
||||
/// 数据对应的位置坐标是否忽略(忽略时连线是透明的),dataIgnore 和 dataPoints 一一对应。
|
||||
/// </summary>
|
||||
public List<bool> dataIgnores = new List<bool>();
|
||||
/// <summary>
|
||||
/// 排序后的数据
|
||||
/// </summary>
|
||||
public List<SerieData> sortedData = new List<SerieData>();
|
||||
/// <summary>
|
||||
/// theme的颜色索引
|
||||
/// </summary>
|
||||
internal int colorIndex;
|
||||
/// <summary>
|
||||
/// 绘制点
|
||||
/// </summary>
|
||||
internal List<PointInfo> drawPoints = new List<PointInfo>();
|
||||
public SerieParams param = new SerieParams();
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/SerieContext.cs.meta
Normal file
11
Runtime/Serie/SerieContext.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87f333572a32a4cb39aa0a05ed97983a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
423
Runtime/Serie/SerieData.cs
Normal file
423
Runtime/Serie/SerieData.cs
Normal file
@@ -0,0 +1,423 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
/// <summary>
|
||||
/// A data item of serie.
|
||||
/// 系列中的一个数据项。可存储数据名和1-n维个数据。
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class SerieData : ChildComponent
|
||||
{
|
||||
[SerializeField] private string m_Name;
|
||||
[SerializeField] private string m_Uuid;
|
||||
[SerializeField] private bool m_Selected;
|
||||
[SerializeField] private bool m_Ignore = false;
|
||||
[SerializeField] private float m_Radius;
|
||||
[SerializeField] private List<ItemStyle> m_ItemStyles = new List<ItemStyle>();
|
||||
[SerializeField] private List<LabelStyle> m_Labels = new List<LabelStyle>();
|
||||
[SerializeField] private List<LabelLine> m_LabelLines = new List<LabelLine>();
|
||||
[SerializeField] private List<Emphasis> m_Emphases = new List<Emphasis>();
|
||||
[SerializeField] private List<SymbolStyle> m_Symbols = new List<SymbolStyle>();
|
||||
[SerializeField] private List<IconStyle> m_IconStyles = new List<IconStyle>();
|
||||
[SerializeField] private List<double> m_Data = new List<double>();
|
||||
[SerializeField] private List<int> m_Children = new List<int>();
|
||||
|
||||
[NonSerialized] public SerieDataContext context = new SerieDataContext();
|
||||
[NonSerialized] public InteractData interact = new InteractData();
|
||||
public ChartLabel labelObject { get; set; }
|
||||
|
||||
private bool m_Show = true;
|
||||
|
||||
/// <summary>
|
||||
/// the name of data item.
|
||||
/// 数据项名称。
|
||||
/// </summary>
|
||||
public string name { get { return m_Name; } set { m_Name = value; } }
|
||||
/// <summary>
|
||||
/// 数据项的唯一id。唯一id不是必须设置的。
|
||||
/// </summary>
|
||||
public string uuid { get { return m_Uuid; } set { m_Uuid = value; } }
|
||||
/// <summary>
|
||||
/// 数据项图例名称。当数据项名称不为空时,图例名称即为系列名称;反之则为索引index。
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string legendName { get { return string.IsNullOrEmpty(name) ? ChartCached.IntToStr(index) : name; } }
|
||||
/// <summary>
|
||||
/// 自定义半径。可用在饼图中自定义某个数据项的半径。
|
||||
/// </summary>
|
||||
public float radius { get { return m_Radius; } set { m_Radius = value; } }
|
||||
/// <summary>
|
||||
/// Whether the data item is selected.
|
||||
/// 该数据项是否被选中。
|
||||
/// </summary>
|
||||
public bool selected { get { return m_Selected; } set { m_Selected = value; } }
|
||||
/// <summary>
|
||||
/// the icon of data.
|
||||
/// 数据项图标样式。
|
||||
/// </summary>
|
||||
public IconStyle iconStyle { get { return m_IconStyles.Count > 0 ? m_IconStyles[0] : null; } }
|
||||
/// <summary>
|
||||
/// 单个数据项的标签设置。
|
||||
/// </summary>
|
||||
public LabelStyle label { get { return m_Labels.Count > 0 ? m_Labels[0] : null; } }
|
||||
public LabelLine labelLine { get { return m_LabelLines.Count > 0 ? m_LabelLines[0] : null; } }
|
||||
/// <summary>
|
||||
/// 单个数据项的样式设置。
|
||||
/// </summary>
|
||||
public ItemStyle itemStyle { get { return m_ItemStyles.Count > 0 ? m_ItemStyles[0] : null; } }
|
||||
/// <summary>
|
||||
/// 单个数据项的高亮样式设置。
|
||||
/// </summary>
|
||||
public Emphasis emphasis { get { return m_Emphases.Count > 0 ? m_Emphases[0] : null; } }
|
||||
/// <summary>
|
||||
/// 单个数据项的标记设置。
|
||||
/// </summary>
|
||||
public SymbolStyle symbol { get { return m_Symbols.Count > 0 ? m_Symbols[0] : null; } }
|
||||
/// <summary>
|
||||
/// 是否忽略数据。当为 true 时,数据不进行绘制。
|
||||
/// </summary>
|
||||
public bool ignore
|
||||
{
|
||||
get { return m_Ignore; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_Ignore, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// An arbitrary dimension data list of data item.
|
||||
/// 可指定任意维数的数值列表。
|
||||
/// </summary>
|
||||
public List<double> data { get { return m_Data; } set { m_Data = value; } }
|
||||
|
||||
public List<int> children { get { return m_Children; } set { m_Children = value; } }
|
||||
/// <summary>
|
||||
/// [default:true] Whether the data item is showed.
|
||||
/// 该数据项是否要显示。
|
||||
/// </summary>
|
||||
public bool show { get { return m_Show; } set { m_Show = value; } }
|
||||
|
||||
private List<double> m_PreviousData = new List<double>();
|
||||
private List<float> m_DataUpdateTime = new List<float>();
|
||||
private List<bool> m_DataUpdateFlag = new List<bool>();
|
||||
private List<Vector2> m_PolygonPoints = new List<Vector2>();
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
index = 0;
|
||||
labelObject = null;
|
||||
m_Name = string.Empty;
|
||||
m_Show = true;
|
||||
m_Selected = false;
|
||||
context.canShowLabel = true;
|
||||
context.highlight = false;
|
||||
m_Radius = 0;
|
||||
interact.Reset();
|
||||
m_Data.Clear();
|
||||
m_PreviousData.Clear();
|
||||
m_DataUpdateTime.Clear();
|
||||
m_DataUpdateFlag.Clear();
|
||||
m_IconStyles.Clear();
|
||||
m_Labels.Clear();
|
||||
m_LabelLines.Clear();
|
||||
m_ItemStyles.Clear();
|
||||
m_Emphases.Clear();
|
||||
m_Symbols.Clear();
|
||||
}
|
||||
|
||||
public T GetOrAddComponent<T>() where T : ChildComponent
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (type == typeof(ItemStyle))
|
||||
{
|
||||
if (m_ItemStyles.Count == 0)
|
||||
m_ItemStyles.Add(new ItemStyle() { show = true });
|
||||
return m_ItemStyles[0] as T;
|
||||
}
|
||||
else if (type == typeof(IconStyle))
|
||||
{
|
||||
if (m_IconStyles.Count == 0)
|
||||
m_IconStyles.Add(new IconStyle() { show = true });
|
||||
return m_IconStyles[0] as T;
|
||||
}
|
||||
else if (type == typeof(LabelStyle))
|
||||
{
|
||||
if (m_Labels.Count == 0)
|
||||
m_Labels.Add(new LabelStyle() { show = true });
|
||||
return m_Labels[0] as T;
|
||||
}
|
||||
else if (type == typeof(LabelLine))
|
||||
{
|
||||
if (m_LabelLines.Count == 0)
|
||||
m_LabelLines.Add(new LabelLine() { show = true });
|
||||
return m_LabelLines[0] as T;
|
||||
}
|
||||
else if (type == typeof(Emphasis))
|
||||
{
|
||||
if (m_Emphases.Count == 0)
|
||||
m_Emphases.Add(new Emphasis() { show = true });
|
||||
return m_Emphases[0] as T;
|
||||
}
|
||||
else if (type == typeof(SymbolStyle))
|
||||
{
|
||||
if (m_Symbols.Count == 0)
|
||||
m_Symbols.Add(new SymbolStyle() { show = true });
|
||||
return m_Symbols[0] as T;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.Exception("SerieData not support component:" + type);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAllComponent()
|
||||
{
|
||||
m_ItemStyles.Clear();
|
||||
m_IconStyles.Clear();
|
||||
m_Labels.Clear();
|
||||
m_LabelLines.Clear();
|
||||
m_Symbols.Clear();
|
||||
m_Emphases.Clear();
|
||||
}
|
||||
|
||||
public void RemoveComponent<T>() where T : ISerieDataComponent
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (type == typeof(ItemStyle))
|
||||
m_ItemStyles.Clear();
|
||||
else if (type == typeof(IconStyle))
|
||||
m_IconStyles.Clear();
|
||||
else if (type == typeof(LabelStyle))
|
||||
m_Labels.Clear();
|
||||
else if (type == typeof(LabelLine))
|
||||
m_LabelLines.Clear();
|
||||
else if (type == typeof(Emphasis))
|
||||
m_Emphases.Clear();
|
||||
else if (type == typeof(SymbolStyle))
|
||||
m_Symbols.Clear();
|
||||
else
|
||||
throw new System.Exception("SerieData not support component:" + type);
|
||||
}
|
||||
public double GetData(int index, bool inverse = false)
|
||||
{
|
||||
if (index >= 0 && index < m_Data.Count)
|
||||
{
|
||||
return inverse ? -m_Data[index] : m_Data[index];
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
public double GetData(int index, double min, double max)
|
||||
{
|
||||
if (index >= 0 && index < m_Data.Count)
|
||||
{
|
||||
var value = m_Data[index];
|
||||
if (value < min) return min;
|
||||
else if (value > max) return max;
|
||||
else return value;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
public double GetPreviousData(int index, bool inverse = false)
|
||||
{
|
||||
if (index >= 0 && index < m_PreviousData.Count)
|
||||
{
|
||||
return inverse ? -m_PreviousData[index] : m_PreviousData[index];
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
public double GetFirstData(float animationDuration = 500f)
|
||||
{
|
||||
if (m_Data.Count > 0) return GetCurrData(0, animationDuration);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double GetLastData()
|
||||
{
|
||||
if (m_Data.Count > 0) return m_Data[m_Data.Count - 1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double GetCurrData(int index, float animationDuration = 500f, bool inverse = false)
|
||||
{
|
||||
return GetCurrData(index, animationDuration, inverse, 0, 0);
|
||||
}
|
||||
|
||||
public double GetCurrData(int index, float animationDuration, bool inverse, double min, double max)
|
||||
{
|
||||
if (index < m_DataUpdateFlag.Count && m_DataUpdateFlag[index] && animationDuration > 0)
|
||||
{
|
||||
var time = Time.time - m_DataUpdateTime[index];
|
||||
var total = animationDuration / 1000;
|
||||
|
||||
var rate = time / total;
|
||||
if (rate > 1) rate = 1;
|
||||
if (rate < 1)
|
||||
{
|
||||
CheckLastData();
|
||||
var curr = MathUtil.Lerp(GetPreviousData(index), GetData(index), rate);
|
||||
if (min != 0 || max != 0)
|
||||
{
|
||||
if (inverse)
|
||||
{
|
||||
var temp = min;
|
||||
min = -max;
|
||||
max = -temp;
|
||||
}
|
||||
var pre = m_PreviousData[index];
|
||||
if (pre < min)
|
||||
{
|
||||
m_PreviousData[index] = min;
|
||||
curr = min;
|
||||
}
|
||||
else if (pre > max)
|
||||
{
|
||||
m_PreviousData[index] = max;
|
||||
curr = max;
|
||||
}
|
||||
}
|
||||
curr = inverse ? -curr : curr;
|
||||
return curr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DataUpdateFlag[index] = false;
|
||||
return GetData(index, inverse);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetData(index, inverse);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the maxinum value.
|
||||
/// 最大值。
|
||||
/// </summary>
|
||||
public double GetMaxData(bool inverse = false)
|
||||
{
|
||||
if (m_Data.Count == 0) return 0;
|
||||
var temp = double.MinValue;
|
||||
for (int i = 0; i < m_Data.Count; i++)
|
||||
{
|
||||
var value = GetData(i, inverse);
|
||||
if (value > temp) temp = value;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the mininum value.
|
||||
/// 最小值。
|
||||
/// </summary>
|
||||
public double GetMinData(bool inverse = false)
|
||||
{
|
||||
if (m_Data.Count == 0) return 0;
|
||||
var temp = double.MaxValue;
|
||||
for (int i = 0; i < m_Data.Count; i++)
|
||||
{
|
||||
var value = GetData(i, inverse);
|
||||
if (value < temp) temp = value;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
public bool UpdateData(int dimension, double value, bool updateAnimation, float animationDuration = 500f)
|
||||
{
|
||||
if (dimension >= 0 && dimension < data.Count)
|
||||
{
|
||||
CheckLastData();
|
||||
m_PreviousData[dimension] = GetCurrData(dimension, animationDuration);
|
||||
//m_PreviousData[dimension] = data[dimension];;
|
||||
m_DataUpdateTime[dimension] = Time.time;
|
||||
m_DataUpdateFlag[dimension] = updateAnimation;
|
||||
data[dimension] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UpdateData(int dimension, double value)
|
||||
{
|
||||
if (dimension >= 0 && dimension < data.Count)
|
||||
{
|
||||
data[dimension] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CheckLastData()
|
||||
{
|
||||
if (m_PreviousData.Count != m_Data.Count)
|
||||
{
|
||||
m_PreviousData.Clear();
|
||||
m_DataUpdateTime.Clear();
|
||||
m_DataUpdateFlag.Clear();
|
||||
for (int i = 0; i < m_Data.Count; i++)
|
||||
{
|
||||
m_PreviousData.Add(m_Data[i]);
|
||||
m_DataUpdateTime.Add(Time.time);
|
||||
m_DataUpdateFlag.Add(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDataChanged()
|
||||
{
|
||||
foreach (var b in m_DataUpdateFlag)
|
||||
if (b) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public float GetLabelWidth()
|
||||
{
|
||||
if (labelObject != null) return labelObject.GetLabelWidth();
|
||||
else return 0;
|
||||
}
|
||||
|
||||
public float GetLabelHeight()
|
||||
{
|
||||
if (labelObject != null) return labelObject.GetLabelHeight();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetLabelActive(bool flag)
|
||||
{
|
||||
if (labelObject != null) labelObject.SetLabelActive(flag);
|
||||
}
|
||||
public void SetIconActive(bool flag)
|
||||
{
|
||||
if (labelObject != null) labelObject.SetIconActive(flag);
|
||||
}
|
||||
|
||||
public void SetPolygon(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
|
||||
{
|
||||
m_PolygonPoints.Clear();
|
||||
m_PolygonPoints.Add(p1);
|
||||
m_PolygonPoints.Add(p2);
|
||||
m_PolygonPoints.Add(p3);
|
||||
m_PolygonPoints.Add(p4);
|
||||
}
|
||||
|
||||
public bool IsInPolygon(Vector2 p)
|
||||
{
|
||||
if (m_PolygonPoints.Count == 0) return false;
|
||||
var inside = false;
|
||||
var j = m_PolygonPoints.Count - 1;
|
||||
for (int i = 0; i < m_PolygonPoints.Count; j = i++)
|
||||
{
|
||||
var pi = m_PolygonPoints[i];
|
||||
var pj = m_PolygonPoints[j];
|
||||
if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
|
||||
(p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
|
||||
inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/SerieData.cs.meta
Normal file
11
Runtime/Serie/SerieData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbf44007311214228976678a623479b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
60
Runtime/Serie/SerieDataContext.cs
Normal file
60
Runtime/Serie/SerieDataContext.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class SerieDataContext
|
||||
{
|
||||
public Vector3 labelPosition { get; set; }
|
||||
/// <summary>
|
||||
/// 开始角度
|
||||
/// </summary>
|
||||
public float startAngle { get; internal set; }
|
||||
/// <summary>
|
||||
/// 结束角度
|
||||
/// </summary>
|
||||
public float toAngle { get; internal set; }
|
||||
/// <summary>
|
||||
/// 一半时的角度
|
||||
/// </summary>
|
||||
public float halfAngle { get; internal set; }
|
||||
/// <summary>
|
||||
/// 当前角度
|
||||
/// </summary>
|
||||
public float currentAngle { get; internal set; }
|
||||
/// <summary>
|
||||
/// 饼图数据项的内半径
|
||||
/// </summary>
|
||||
public float insideRadius { get; internal set; }
|
||||
/// <summary>
|
||||
/// 饼图数据项的偏移半径
|
||||
/// </summary>
|
||||
public float offsetRadius { get; internal set; }
|
||||
public float outsideRadius { get; set; }
|
||||
public Vector3 position { get; set; }
|
||||
public List<Vector3> dataPoints = new List<Vector3>();
|
||||
/// <summary>
|
||||
/// 绘制区域。
|
||||
/// </summary>
|
||||
public Rect rect { get; set; }
|
||||
public Rect subRect { get; set; }
|
||||
public int level { get; set; }
|
||||
public SerieData parent { get; set; }
|
||||
public Color32 color { get; set; }
|
||||
public double area { get; set; }
|
||||
public float angle { get; set; }
|
||||
public Vector3 offsetCenter { get; set; }
|
||||
public float stackHeight { get; set; }
|
||||
|
||||
public bool canShowLabel = true;
|
||||
public Image symbol { get; set; }
|
||||
/// <summary>
|
||||
/// Whether the data item is highlighted.
|
||||
/// 该数据项是否被高亮,一般由鼠标悬停或图例悬停触发高亮。
|
||||
/// </summary>
|
||||
public bool highlight { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/SerieDataContext.cs.meta
Normal file
11
Runtime/Serie/SerieDataContext.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fa67a86e80b4456cbe76ef4b330f3fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
351
Runtime/Serie/SerieHandler.cs
Normal file
351
Runtime/Serie/SerieHandler.cs
Normal file
@@ -0,0 +1,351 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public abstract class SerieHandler
|
||||
{
|
||||
public BaseChart chart { get; internal set; }
|
||||
public SerieHandlerAttribute attribute { get; internal set; }
|
||||
|
||||
public virtual void InitComponent() { }
|
||||
public virtual void RemoveComponent() { }
|
||||
public virtual void CheckComponent(StringBuilder sb) { }
|
||||
public virtual void Update() { }
|
||||
public virtual void DrawBase(VertexHelper vh) { }
|
||||
public virtual void DrawSerie(VertexHelper vh) { }
|
||||
public virtual void DrawTop(VertexHelper vh) { }
|
||||
public virtual void OnPointerClick(PointerEventData eventData) { }
|
||||
public virtual void OnPointerDown(PointerEventData eventData) { }
|
||||
public virtual void OnPointerUp(PointerEventData eventData) { }
|
||||
public virtual void OnPointerEnter(PointerEventData eventData) { }
|
||||
public virtual void OnPointerExit(PointerEventData eventData) { }
|
||||
public virtual void OnDrag(PointerEventData eventData) { }
|
||||
public virtual void OnBeginDrag(PointerEventData eventData) { }
|
||||
public virtual void OnEndDrag(PointerEventData eventData) { }
|
||||
public virtual void OnScroll(PointerEventData eventData) { }
|
||||
public virtual void RefreshLabelNextFrame() { }
|
||||
public virtual void RefreshLabelInternal() { }
|
||||
public virtual void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category, string marker, string itemFormatter, string numericFormatter, ref List<SerieParams> paramList, ref string title) { }
|
||||
public virtual void OnLegendButtonClick(int index, string legendName, bool show) { }
|
||||
public virtual void OnLegendButtonEnter(int index, string legendName) { }
|
||||
public virtual void OnLegendButtonExit(int index, string legendName) { }
|
||||
internal abstract void SetSerie(Serie serie);
|
||||
}
|
||||
|
||||
public abstract class SerieHandler<T> : SerieHandler where T : Serie
|
||||
{
|
||||
private static readonly string s_SerieLabelObjectName = "label";
|
||||
private static readonly string s_SerieTitleObjectName = "serie";
|
||||
protected GameObject m_SerieRoot;
|
||||
protected bool m_InitedLabel;
|
||||
protected bool m_RefreshLabel;
|
||||
protected bool m_LastCheckContextFlag = false;
|
||||
protected bool m_LegendEnter = false;
|
||||
protected int m_LegendEnterIndex;
|
||||
|
||||
public T serie { get; internal set; }
|
||||
|
||||
internal override void SetSerie(Serie serie)
|
||||
{
|
||||
this.serie = (T)serie;
|
||||
this.serie.context.param.serieType = typeof(T);
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
if (m_RefreshLabel)
|
||||
{
|
||||
m_RefreshLabel = false;
|
||||
if (m_InitedLabel)
|
||||
RefreshLabelInternal();
|
||||
}
|
||||
if (serie.label != null && (serie.labelDirty || serie.label.componentDirty))
|
||||
{
|
||||
serie.labelDirty = false;
|
||||
serie.label.ClearComponentDirty();
|
||||
InitSerieLabel();
|
||||
}
|
||||
if (serie.titleDirty || serie.titleStyle.componentDirty)
|
||||
{
|
||||
serie.titleDirty = false;
|
||||
serie.titleStyle.ClearComponentDirty();
|
||||
InitSerieTitle();
|
||||
}
|
||||
if (serie.nameDirty)
|
||||
{
|
||||
foreach (var component in chart.components)
|
||||
{
|
||||
if (component is Legend)
|
||||
component.SetAllDirty();
|
||||
}
|
||||
chart.RefreshChart();
|
||||
serie.ClearSerieNameDirty();
|
||||
}
|
||||
if (serie.vertsDirty)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
serie.ClearVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override void RefreshLabelNextFrame()
|
||||
{
|
||||
m_RefreshLabel = true;
|
||||
}
|
||||
|
||||
public override void InitComponent()
|
||||
{
|
||||
InitRoot();
|
||||
InitSerieLabel();
|
||||
InitSerieTitle();
|
||||
}
|
||||
|
||||
public override void RemoveComponent()
|
||||
{
|
||||
ChartHelper.SetActive(m_SerieRoot, false);
|
||||
}
|
||||
|
||||
public override void OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (serie.IsLegendName(legendName))
|
||||
{
|
||||
chart.SetSerieActive(serie, show);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (serie.IsLegendName(legendName))
|
||||
{
|
||||
m_LegendEnter = true;
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (serie.IsLegendName(legendName))
|
||||
{
|
||||
m_LegendEnter = false;
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitRoot()
|
||||
{
|
||||
m_InitedLabel = false;
|
||||
var objName = s_SerieTitleObjectName + "_" + serie.index;
|
||||
m_SerieRoot = ChartHelper.AddObject(objName, chart.transform, chart.chartMinAnchor,
|
||||
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
|
||||
m_SerieRoot.hideFlags = chart.chartHideFlags;
|
||||
ChartHelper.SetActive(m_SerieRoot, true);
|
||||
ChartHelper.HideAllObject(m_SerieRoot);
|
||||
}
|
||||
|
||||
private void InitSerieLabel()
|
||||
{
|
||||
if (m_SerieRoot == null)
|
||||
InitRoot();
|
||||
var serieLabelRoot = ChartHelper.AddObject(s_SerieLabelObjectName, m_SerieRoot.transform, chart.chartMinAnchor,
|
||||
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
|
||||
serieLabelRoot.hideFlags = chart.chartHideFlags;
|
||||
SerieLabelPool.ReleaseAll(serieLabelRoot.transform);
|
||||
int count = 0;
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
serieData.index = count;
|
||||
serieData.labelObject = null;
|
||||
if (AddSerieLabel(serieLabelRoot, serie, serieData, ref count))
|
||||
{
|
||||
m_InitedLabel = true;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected bool AddSerieLabel(GameObject serieLabelRoot, Serie serie, SerieData serieData, ref int count)
|
||||
{
|
||||
if (serieLabelRoot == null)
|
||||
return false;
|
||||
if (serie.IsPerformanceMode())
|
||||
return false;
|
||||
|
||||
if (count == -1) count = serie.dataCount;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (serieLabel == null)
|
||||
return false;
|
||||
|
||||
var serieEmphasisLabel = SerieHelper.GetSerieEmphasisLabel(serie, serieData);
|
||||
var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
|
||||
|
||||
if (!serieLabel.show && (serieEmphasisLabel == null || !serieEmphasisLabel.show)
|
||||
&& (iconStyle != null && !iconStyle.show))
|
||||
return false;
|
||||
|
||||
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, serie.index, serieData.index);
|
||||
var color = chart.theme.common.textColor;
|
||||
var iconWidth = iconStyle != null ? iconStyle.width : 20;
|
||||
var iconHeight = iconStyle != null ? iconStyle.height : 20;
|
||||
var labelObj = SerieLabelPool.Get(textName, serieLabelRoot.transform, serieLabel, color,
|
||||
iconWidth, iconHeight, chart.theme);
|
||||
var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
|
||||
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
|
||||
var item = ChartHelper.GetOrAddComponent<ChartLabel>(labelObj);
|
||||
item.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
|
||||
item.SetIcon(iconImage);
|
||||
item.SetIconActive(iconStyle != null && iconStyle.show);
|
||||
item.color = serieLabel.textStyle.backgroundColor;
|
||||
serieData.labelObject = item;
|
||||
|
||||
foreach (var data in serieData.children)
|
||||
{
|
||||
AddSerieLabel(serieLabelRoot, serie, serie.GetSerieData(data), ref count);
|
||||
count++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitSerieTitle()
|
||||
{
|
||||
if (m_SerieRoot == null)
|
||||
InitRoot();
|
||||
var textStyle = serie.titleStyle.textStyle;
|
||||
var titleColor = ChartHelper.IsClearColor(textStyle.color) ? chart.theme.GetColor(serie.index) : (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", m_SerieRoot.transform, anchorMin, anchorMax,
|
||||
pivot, sizeDelta, textStyle, chart.theme.common);
|
||||
txt.SetText("");
|
||||
txt.SetColor(titleColor);
|
||||
txt.SetLocalPosition(Vector2.zero);
|
||||
txt.SetLocalEulerAngles(Vector2.zero);
|
||||
txt.SetActive(serie.titleStyle.show);
|
||||
serie.titleStyle.runtimeText = txt;
|
||||
serie.titleStyle.UpdatePosition(serie.context.center);
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData != null)
|
||||
{
|
||||
txt.SetText(serieData.name);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RefreshLabelInternal()
|
||||
{
|
||||
if (!m_InitedLabel)
|
||||
return;
|
||||
|
||||
var colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
var total = serie.yTotal;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.labelObject == null)
|
||||
continue;
|
||||
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
|
||||
var isIgnore = serie.IsIgnoreIndex(serieData.index);
|
||||
serieData.labelObject.SetPosition(serieData.context.position);
|
||||
serieData.labelObject.UpdateIcon(iconStyle);
|
||||
if (serie.show && serieLabel != null && serieLabel.show && serieData.context.canShowLabel && !isIgnore)
|
||||
{
|
||||
var value = serieData.GetData(1);
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
|
||||
serieLabel, chart.theme.GetColor(colorIndex));
|
||||
var invert = serieLabel.autoOffset
|
||||
&& serie is Line
|
||||
&& SerieHelper.IsDownPoint(serie, serieData.index)
|
||||
&& (serie.areaStyle == null || !serie.areaStyle.show);
|
||||
SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, chart.theme);
|
||||
serieData.SetLabelActive(!isIgnore);
|
||||
serieData.labelObject.SetPosition(serieData.context.position + (invert ? -serieLabel.offset : serieLabel.offset));
|
||||
serieData.labelObject.SetText(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateCoordSerieParams(ref List<SerieParams> paramList, ref string title,
|
||||
int dataIndex, bool showCategory, string category, string marker,
|
||||
string itemFormatter, string numericFormatter)
|
||||
{
|
||||
if (dataIndex < 0)
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.category = category;
|
||||
param.dimension = 1;
|
||||
param.serieData = serieData;
|
||||
param.value = serieData.GetData(1);
|
||||
param.total = serie.yTotal;
|
||||
param.color = chart.GetLegendRealShowNameColor(serie.serieName);
|
||||
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(showCategory ? category : serie.serieName);
|
||||
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
|
||||
protected void UpdateItemSerieParams(ref List<SerieParams> paramList, ref string title,
|
||||
int dataIndex, string category, string marker,
|
||||
string itemFormatter, string numericFormatter, int dimension = 1)
|
||||
{
|
||||
if (dataIndex < 0)
|
||||
dataIndex = serie.context.pointerItemDataIndex;
|
||||
|
||||
if (dataIndex < 0)
|
||||
return;
|
||||
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (serieData == null)
|
||||
return;
|
||||
|
||||
var param = serie.context.param;
|
||||
param.serieName = serie.serieName;
|
||||
param.serieIndex = serie.index;
|
||||
param.category = category;
|
||||
param.dimension = dimension;
|
||||
param.serieData = serieData;
|
||||
param.value = serieData.GetData(param.dimension);
|
||||
param.total = SerieHelper.GetMaxData(serie, dimension);
|
||||
param.color = chart.theme.GetColor(dataIndex);
|
||||
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
|
||||
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
|
||||
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter); ;
|
||||
param.columns.Clear();
|
||||
|
||||
param.columns.Add(param.marker);
|
||||
param.columns.Add(serieData.name);
|
||||
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
|
||||
|
||||
paramList.Add(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/SerieHandler.cs.meta
Normal file
11
Runtime/Serie/SerieHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f2bc0a6a80a84eae9c87842c954bc32
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Runtime/Serie/SerieParams.cs
Normal file
24
Runtime/Serie/SerieParams.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class SerieParams
|
||||
{
|
||||
public Type serieType;
|
||||
public int serieIndex;
|
||||
public string serieName;
|
||||
public string marker = "●";
|
||||
public string category;
|
||||
public int dimension;
|
||||
public SerieData serieData;
|
||||
public double value;
|
||||
public double total;
|
||||
public Color32 color;
|
||||
public string itemFormatter;
|
||||
public string numericFormatter;
|
||||
public List<string> columns = new List<string>();
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/SerieParams.cs.meta
Normal file
11
Runtime/Serie/SerieParams.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c46808eb5842743c5b02d03c4c503228
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user