Files
XCharts/Runtime/Serie/Line/LineHandler.GridCoord.cs

400 lines
17 KiB
C#
Raw Normal View History

using System.Collections.Generic;
2021-11-23 13:20:07 +08:00
using System.Text;
using UnityEngine;
using UnityEngine.UI;
2021-01-11 08:54:28 +08:00
using XUGL;
2022-02-19 22:37:57 +08:00
namespace XCharts.Runtime
{
2021-11-23 13:20:07 +08:00
/// <summary>
/// For grid coord
/// </summary>
internal sealed partial class LineHandler : SerieHandler<Line>
{
2021-11-23 13:20:07 +08:00
List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
2021-12-23 13:23:18 +08:00
private GridCoord m_SerieGrid;
2021-11-23 13:20:07 +08:00
2022-05-04 08:45:19 +08:00
public override Vector3 GetSerieDataLabelOffset(SerieData serieData, LabelStyle label)
{
2022-05-22 22:17:38 +08:00
var invert = label.autoOffset &&
SerieHelper.IsDownPoint(serie, serieData.index) &&
(serie.areaStyle == null || !serie.areaStyle.show);
2022-05-04 08:45:19 +08:00
if (invert)
{
var offset = label.GetOffset(serie.context.insideRadius);
return new Vector3(offset.x, -offset.y, offset.z);
}
else
{
return label.GetOffset(serie.context.insideRadius);
}
}
2022-01-26 20:47:14 +08:00
private void UpdateSerieGridContext()
2021-11-23 13:20:07 +08:00
{
2021-12-23 13:23:18 +08:00
if (m_SerieGrid == null)
2021-11-23 13:20:07 +08:00
return;
2022-03-18 08:23:17 +08:00
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
2022-05-22 22:17:38 +08:00
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
2021-12-23 13:23:18 +08:00
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
2022-05-22 22:17:38 +08:00
serie.highlight = false;
serie.ResetInteract();
2021-12-23 13:23:18 +08:00
foreach (var serieData in serie.data)
2022-05-22 22:17:38 +08:00
serieData.context.highlight = false;
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
2021-12-23 13:23:18 +08:00
}
return;
}
m_LastCheckContextFlag = needCheck;
2021-11-23 13:20:07 +08:00
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
2021-12-23 13:23:18 +08:00
var needInteract = false;
serie.ResetDataIndex();
2021-12-24 07:38:10 +08:00
if (m_LegendEnter)
2021-11-23 13:20:07 +08:00
{
serie.context.pointerEnter = true;
2021-12-23 13:23:18 +08:00
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
2021-11-23 13:20:07 +08:00
{
2021-12-23 13:23:18 +08:00
var serieData = serie.data[i];
var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, SerieState.Emphasis);
2021-12-11 18:26:28 +08:00
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, size);
2021-11-23 13:20:07 +08:00
}
2021-12-23 13:23:18 +08:00
}
else if (serie.context.isTriggerByAxis)
{
serie.context.pointerEnter = false;
2021-12-23 13:23:18 +08:00
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
2021-11-23 13:20:07 +08:00
{
2021-12-23 13:23:18 +08:00
var serieData = serie.data[i];
var highlight = i == serie.context.pointerItemDataIndex;
serieData.context.highlight = highlight;
var state = SerieHelper.GetSerieState(serie, serieData, true);
var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, state);
serieData.interact.SetValue(ref needInteract, size);
if (highlight)
2021-12-23 13:23:18 +08:00
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = i;
needInteract = true;
2021-12-23 13:23:18 +08:00
}
2021-11-23 13:20:07 +08:00
}
}
2021-12-23 13:23:18 +08:00
else
{
var lastIndex = serie.context.pointerItemDataIndex;
2021-12-23 13:23:18 +08:00
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
2022-04-09 11:03:41 +08:00
for (int i = 0; i < serie.dataCount; i++)
2021-12-23 13:23:18 +08:00
{
2022-04-09 11:03:41 +08:00
var serieData = serie.data[i];
2021-12-23 13:23:18 +08:00
var dist = Vector3.Distance(chart.pointerPos, serieData.context.position);
var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize);
var highlight = dist <= size;
serieData.context.highlight = highlight;
var state = SerieHelper.GetSerieState(serie, serieData, true);
size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, state);
serieData.interact.SetValue(ref needInteract, size);
if (highlight)
2021-12-23 13:23:18 +08:00
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = serieData.index;
2021-12-23 13:23:18 +08:00
}
}
if (lastIndex != serie.context.pointerItemDataIndex)
{
needInteract = true;
}
if (serie.context.pointerItemDataIndex >= 0)
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
else
serie.interact.SetValue(ref needInteract, lineWidth);
2021-12-23 13:23:18 +08:00
}
if (needInteract)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
2021-11-23 13:20:07 +08:00
}
private void DrawLinePoint(VertexHelper vh, Serie serie)
{
if (!serie.show || serie.IsPerformanceMode())
return;
2021-12-23 13:23:18 +08:00
if (m_SerieGrid == null)
2021-11-23 13:20:07 +08:00
return;
2021-12-23 13:23:18 +08:00
var count = serie.context.dataPoints.Count;
var clip = SeriesHelper.IsAnyClipSerie(chart.series);
2021-11-23 13:20:07 +08:00
var theme = chart.theme;
2021-12-23 13:23:18 +08:00
var interacting = false;
2021-12-28 08:18:24 +08:00
var lineArrow = serie.lineArrow;
2022-05-22 22:17:38 +08:00
var visualMap = chart.GetVisualMapOfSerie(serie);
var isVisualMapGradient = VisualMapHelper.IsNeedLineGradient(visualMap);
Axis axis;
Axis relativedAxis;
chart.GetSerieGridCoordAxis(serie, out axis, out relativedAxis);
2022-05-22 22:17:38 +08:00
2021-01-11 08:54:28 +08:00
for (int i = 0; i < count; i++)
{
var index = serie.context.dataIndexs[i];
var serieData = serie.GetSerieData(index);
2021-12-09 21:35:23 +08:00
if (serieData == null)
continue;
2022-01-26 20:47:14 +08:00
if (serieData.context.isClip)
continue;
var state = SerieHelper.GetSerieState(serie, serieData, true);
var symbol = SerieHelper.GetSerieSymbol(serie, serieData, state);
2021-11-23 13:20:07 +08:00
if (!symbol.show || !symbol.ShowSymbol(index, count))
2021-11-23 13:20:07 +08:00
continue;
2021-12-23 13:23:18 +08:00
var pos = serie.context.dataPoints[i];
2021-12-28 08:18:24 +08:00
if (lineArrow != null && lineArrow.show)
{
2021-12-28 08:18:24 +08:00
if (lineArrow.position == LineArrow.Position.Start && i == 0)
2021-11-23 13:20:07 +08:00
continue;
2021-12-28 08:18:24 +08:00
if (lineArrow.position == LineArrow.Position.End && i == count - 1)
2021-11-23 13:20:07 +08:00
continue;
}
2021-11-23 13:20:07 +08:00
2021-12-23 13:23:18 +08:00
if (ChartHelper.IsIngore(pos))
2021-11-23 13:20:07 +08:00
continue;
var symbolSize = 0f;
2021-12-23 13:23:18 +08:00
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
{
symbolSize = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, chart.theme.serie.lineSymbolSize, state);
2021-12-23 13:23:18 +08:00
serieData.interact.SetValue(ref interacting, symbolSize);
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
}
float symbolBorder = 0f;
float[] cornerRadius = null;
Color32 symbolColor, symbolToColor, symbolEmptyColor, borderColor;
2022-09-21 06:59:57 +08:00
SerieHelper.GetItemColor(out symbolColor, out symbolToColor, out symbolEmptyColor, serie, serieData, theme, serie.context.colorIndex);
SerieHelper.GetSymbolInfo(out borderColor, out symbolBorder, out cornerRadius, serie, null, chart.theme, state);
2022-05-22 22:17:38 +08:00
if (isVisualMapGradient)
{
symbolColor = VisualMapHelper.GetLineGradientColor(visualMap, pos, m_SerieGrid, axis, relativedAxis, symbolColor);
symbolToColor = symbolColor;
}
2021-12-23 13:23:18 +08:00
chart.DrawClipSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
symbolColor, symbolToColor, symbolEmptyColor, borderColor, symbol.gap, clip, cornerRadius, m_SerieGrid,
2021-12-23 13:23:18 +08:00
i > 0 ? serie.context.dataPoints[i - 1] : m_SerieGrid.context.position);
}
if (interacting)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
2021-11-23 13:20:07 +08:00
private void DrawLineArrow(VertexHelper vh, Serie serie)
{
2021-12-28 08:18:24 +08:00
if (!serie.show || serie.lineArrow == null || !serie.lineArrow.show)
2021-11-23 13:20:07 +08:00
return;
2021-12-08 13:36:02 +08:00
if (serie.context.dataPoints.Count < 2)
2021-11-23 13:20:07 +08:00
return;
2022-09-21 06:59:57 +08:00
var lineColor = SerieHelper.GetLineColor(serie, null, chart.theme, serie.context.colorIndex);
2021-11-23 13:20:07 +08:00
var startPos = Vector3.zero;
var arrowPos = Vector3.zero;
2021-01-11 08:54:28 +08:00
var lineArrow = serie.lineArrow.arrow;
2021-12-08 13:36:02 +08:00
var dataPoints = serie.context.drawPoints;
2021-01-11 08:54:28 +08:00
switch (serie.lineArrow.position)
{
2021-01-11 08:54:28 +08:00
case LineArrow.Position.End:
if (dataPoints.Count < 3)
{
2021-12-08 13:36:02 +08:00
startPos = dataPoints[dataPoints.Count - 2].position;
arrowPos = dataPoints[dataPoints.Count - 1].position;
2021-01-11 08:54:28 +08:00
}
else
{
2021-12-08 13:36:02 +08:00
startPos = dataPoints[dataPoints.Count - 3].position;
arrowPos = dataPoints[dataPoints.Count - 2].position;
2021-01-11 08:54:28 +08:00
}
UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
2021-11-23 13:20:07 +08:00
2021-01-11 08:54:28 +08:00
break;
2021-11-23 13:20:07 +08:00
2021-01-11 08:54:28 +08:00
case LineArrow.Position.Start:
2021-12-08 13:36:02 +08:00
startPos = dataPoints[1].position;
arrowPos = dataPoints[0].position;
2021-01-11 08:54:28 +08:00
UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
2021-11-23 13:20:07 +08:00
lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
2021-01-11 08:54:28 +08:00
break;
}
}
2021-12-08 08:31:32 +08:00
private void DrawLineSerie(VertexHelper vh, Line serie)
{
2021-11-23 13:20:07 +08:00
if (serie.animation.HasFadeOut())
return;
2021-12-08 08:31:32 +08:00
Axis axis;
Axis relativedAxis;
2022-07-05 21:43:09 +08:00
var isY = chart.GetSerieGridCoordAxis(serie, out axis, out relativedAxis);
2021-12-08 08:31:32 +08:00
if (axis == null)
2021-11-23 13:20:07 +08:00
return;
2021-12-08 08:31:32 +08:00
if (relativedAxis == null)
2021-11-23 13:20:07 +08:00
return;
2022-01-26 20:47:14 +08:00
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
2021-12-23 13:23:18 +08:00
if (m_SerieGrid == null)
2021-11-23 13:20:07 +08:00
return;
if (m_EndLabel != null && !m_SerieGrid.context.endLabelList.Contains(m_EndLabel))
{
m_SerieGrid.context.endLabelList.Add(m_EndLabel);
}
2021-11-23 13:20:07 +08:00
var visualMap = chart.GetVisualMapOfSerie(serie);
2021-12-08 08:31:32 +08:00
var dataZoom = chart.GetDataZoomOfAxis(axis);
2021-01-11 08:54:28 +08:00
var showData = serie.GetDataList(dataZoom);
2021-11-23 13:20:07 +08:00
if (showData.Count <= 0)
return;
2021-12-23 13:23:18 +08:00
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
2021-12-08 08:31:32 +08:00
var scaleWid = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
2022-05-22 22:17:38 +08:00
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
2021-12-23 13:23:18 +08:00
int rate = LineHelper.GetDataAverageRate(serie, m_SerieGrid, maxCount, false);
2022-05-22 22:17:38 +08:00
var totalAverage = serie.sampleAverage > 0 ?
serie.sampleAverage :
DataHelper.DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
2019-11-30 21:24:04 +08:00
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var unscaledTime = serie.animation.unscaledTime;
2021-11-23 13:20:07 +08:00
2021-12-23 13:23:18 +08:00
var interacting = false;
var lineWidth = LineHelper.GetLineWidth(ref interacting, serie, chart.theme.serie.lineWidth);
2021-12-08 08:31:32 +08:00
axis.context.scaleWidth = scaleWid;
2021-12-23 13:23:18 +08:00
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
2021-11-23 13:20:07 +08:00
2021-12-08 08:31:32 +08:00
Serie lastSerie = null;
var isStack = SeriesHelper.IsStack<Line>(chart.series, serie.stack);
2021-11-23 13:20:07 +08:00
if (isStack)
2021-12-08 08:31:32 +08:00
{
lastSerie = SeriesHelper.GetLastStackSerie(chart.series, serie);
2021-11-23 13:20:07 +08:00
SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
2021-12-08 08:31:32 +08:00
}
2022-01-26 20:47:14 +08:00
var lp = Vector3.zero;
2021-12-08 08:31:32 +08:00
for (int i = serie.minShow; i < maxCount; i += rate)
{
2021-12-08 08:31:32 +08:00
var serieData = showData[i];
var isIgnore = serie.IsIgnoreValue(serieData);
if (isIgnore)
{
2021-12-09 07:12:15 +08:00
serieData.context.stackHeight = 0;
serieData.context.position = Vector3.zero;
2021-12-23 13:23:18 +08:00
if (serie.ignoreLineBreak && serie.context.dataIgnores.Count > 0)
2021-12-08 08:31:32 +08:00
{
2021-12-23 13:23:18 +08:00
serie.context.dataIgnores[serie.context.dataIgnores.Count - 1] = true;
2021-12-08 08:31:32 +08:00
}
}
else
{
2021-12-08 08:31:32 +08:00
var np = Vector3.zero;
2021-12-08 13:36:02 +08:00
var xValue = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
2021-12-08 08:31:32 +08:00
var relativedValue = DataHelper.SampleValue(ref showData, serie.sampleType, rate, serie.minShow,
maxCount, totalAverage, i, dataChangeDuration, ref dataChanging, relativedAxis, unscaledTime);
2021-12-08 08:31:32 +08:00
2021-12-23 13:23:18 +08:00
serieData.context.stackHeight = GetDataPoint(isY, axis, relativedAxis, m_SerieGrid, xValue, relativedValue,
2021-12-08 08:31:32 +08:00
i, scaleWid, isStack, ref np);
2022-01-26 20:47:14 +08:00
serieData.context.isClip = false;
if (serie.clip && !m_SerieGrid.Contains(np))
{
if (m_SerieGrid.BoundaryPoint(lp, np, ref np))
{
serieData.context.isClip = true;
}
}
serie.context.dataIgnores.Add(false);
2021-12-09 07:12:15 +08:00
serieData.context.position = np;
2021-12-08 13:36:02 +08:00
serie.context.dataPoints.Add(np);
serie.context.dataIndexs.Add(serieData.index);
2022-01-26 20:47:14 +08:00
lp = np;
}
}
2021-11-23 13:20:07 +08:00
2021-12-23 13:23:18 +08:00
if (dataChanging || interacting)
2021-11-23 13:20:07 +08:00
chart.RefreshPainter(serie);
2021-12-08 13:36:02 +08:00
if (serie.context.dataPoints.Count <= 0)
return;
2021-11-23 13:20:07 +08:00
2021-12-08 13:36:02 +08:00
serie.animation.InitProgress(serie.context.dataPoints, isY);
2021-11-23 13:20:07 +08:00
2021-12-08 08:31:32 +08:00
VisualMapHelper.AutoSetLineMinMax(visualMap, serie, isY, axis, relativedAxis);
2022-04-09 21:30:28 +08:00
LineHelper.UpdateSerieDrawPoints(serie, chart.settings, chart.theme, visualMap, lineWidth, isY);
LineHelper.DrawSerieLineArea(vh, serie, lastSerie, chart.theme, visualMap, isY, axis, relativedAxis, m_SerieGrid);
2021-12-23 13:23:18 +08:00
LineHelper.DrawSerieLine(vh, chart.theme, serie, visualMap, m_SerieGrid, axis, relativedAxis, lineWidth);
2021-11-23 13:20:07 +08:00
2021-12-08 08:31:32 +08:00
serie.context.vertCount = vh.currentVertCount;
2021-11-23 13:20:07 +08:00
if (!serie.animation.IsFinish())
{
2021-12-08 08:31:32 +08:00
serie.animation.CheckProgress();
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
2021-11-23 13:20:07 +08:00
chart.RefreshPainter(serie);
}
}
2021-12-08 08:31:32 +08:00
private float GetDataPoint(bool isY, Axis axis, Axis relativedAxis, GridCoord grid, double xValue,
double yValue, int i, float scaleWid, bool isStack, ref Vector3 np)
{
2021-12-08 08:31:32 +08:00
float xPos, yPos;
2021-12-12 18:05:26 +08:00
var gridXY = isY ? grid.context.x : grid.context.y;
2022-01-13 21:45:59 +08:00
var valueHig = 0f;
valueHig = AxisHelper.GetAxisValueDistance(grid, relativedAxis, scaleWid, yValue);
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
2021-12-08 08:31:32 +08:00
if (isY)
{
2021-12-12 18:05:26 +08:00
xPos = gridXY + valueHig;
2022-01-13 21:45:59 +08:00
yPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
2021-01-11 08:54:28 +08:00
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
2021-12-12 18:05:26 +08:00
xPos += m_StackSerieData[n][i].context.stackHeight;
2020-01-15 19:41:21 +08:00
}
}
2021-12-08 08:31:32 +08:00
else
{
2021-12-12 18:05:26 +08:00
yPos = gridXY + valueHig;
2022-01-13 21:45:59 +08:00
xPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
2021-01-11 08:54:28 +08:00
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
2021-12-12 18:05:26 +08:00
yPos += m_StackSerieData[n][i].context.stackHeight;
}
}
2021-12-08 08:31:32 +08:00
np = new Vector3(xPos, yPos);
return AxisHelper.GetAxisValueLength(grid, relativedAxis, scaleWid, yValue);
}
}
}