AirControl  1.3.0
Open Source, Modular, and Extensible Flight Simulator For Deep Learning Research
CoordinateChart.cs
1 /******************************************/
2 /* */
3 /* Copyright (c) 2021 monitor1394 */
4 /* https://github.com/monitor1394 */
5 /* */
6 /******************************************/
7 
8 using UnityEngine;
9 using UnityEngine.UI;
10 using System.Collections.Generic;
11 using System.Text;
12 using XUGL;
13 using System;
14 
15 namespace XCharts
16 {
17  public partial class CoordinateChart : BaseChart
18  {
19  private static readonly string s_DefaultDataZoom = "datazoom";
20  private static readonly string s_DefaultAxisName = "name";
21 
22  protected override void InitComponent()
23  {
24  base.InitComponent();
25  if (m_Grids.Count == 0) m_Grids = new List<Grid>() { Grid.defaultGrid };
26  if (m_DataZooms.Count == 0) m_DataZooms = new List<DataZoom>() { DataZoom.defaultDataZoom };
27  if (m_VisualMaps.Count == 0) m_VisualMaps = new List<VisualMap> { new VisualMap() };
28  InitDefaultAxes();
29  CheckMinMaxValue();
30  InitGrid();
31  InitDataZoom();
32  InitAxisX();
33  InitAxisY();
34  tooltip.UpdateToTop();
35 
36  var handler = new MarkLineHandler(this);
37  m_ComponentHandlers.Add(handler);
38  handler.Init();
39  }
40 
41  protected override void Update()
42  {
43  CheckMinMaxValue();
44  CheckRaycastTarget();
45  base.Update();
46  }
47 
48 #if UNITY_EDITOR
49  protected override void Reset()
50  {
51  base.Reset();
52  m_Grids.Clear();
53  m_DataZooms.Clear();
54  m_VisualMaps.Clear();
55  m_XAxes.Clear();
56  m_YAxes.Clear();
57  Awake();
58  }
59 #endif
60 
61  private void RefreshSeriePainterByGridIndex(int gridIndex)
62  {
63  foreach (var serie in m_Series.list)
64  {
65  var axis = GetXAxis(serie.xAxisIndex);
66  if (axis == null) continue;
67  var grid = GetGrid(axis.index);
68  if (grid == null) continue;
69  if (grid.index == gridIndex)
70  {
71  RefreshPainter(serie);
72  }
73  }
74  }
75 
76  private void RefreshSeriePainterByAxisIndex(Axis axis)
77  {
78  var grid = GetGrid(axis.index);
79  if (grid == null) return;
80  RefreshSeriePainterByGridIndex(grid.index);
81  }
82 
83  public override void OnDataZoomRangeChanged(DataZoom dataZoom)
84  {
85  foreach (var index in dataZoom.xAxisIndexs)
86  {
87  var axis = GetXAxis(index);
88  if (axis != null && axis.show) axis.SetAllDirty();
89  }
90  foreach (var index in dataZoom.yAxisIndexs)
91  {
92  var axis = GetYAxis(index);
93  if (axis != null && axis.show) axis.SetAllDirty();
94  }
95  }
96 
97  protected override void DrawPainterBase(VertexHelper vh)
98  {
99  base.DrawPainterBase(vh);
100  if (!SeriesHelper.IsAnyClipSerie(m_Series))
101  {
102  DrawCoordinate(vh);
103  }
104  }
105 
106  protected override void DrawBackground(VertexHelper vh)
107  {
108  if (SeriesHelper.IsAnyClipSerie(m_Series))
109  {
110  var xLineDiff = xAxis0.axisLine.GetWidth(m_Theme.axis.lineWidth);
111  var yLineDiff = yAxis0.axisLine.GetWidth(m_Theme.axis.lineWidth);
112  var xSplitDiff = xAxis0.splitLine.GetWidth(m_Theme.axis.splitLineWidth);
113  var ySplitDiff = yAxis0.splitLine.GetWidth(m_Theme.axis.splitLineWidth);
114  foreach (var grid in m_Grids)
115  {
116  var cpty = grid.runtimeY + grid.runtimeHeight + ySplitDiff;
117  var cp1 = new Vector3(grid.runtimeX - yLineDiff, grid.runtimeY - xLineDiff);
118  var cp2 = new Vector3(grid.runtimeX - yLineDiff, cpty);
119  var cp3 = new Vector3(grid.runtimeX + grid.runtimeWidth + xSplitDiff, cpty);
120  var cp4 = new Vector3(grid.runtimeX + grid.runtimeWidth + xSplitDiff, grid.runtimeY - xLineDiff);
121  var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
122  UGL.DrawQuadrilateral(vh, cp1, cp2, cp3, cp4, backgroundColor);
123  }
124  }
125  else
126  {
127  base.DrawBackground(vh);
128  }
129  }
130 
131  protected void DrawClip(VertexHelper vh)
132  {
133  if (!SeriesHelper.IsAnyClipSerie(m_Series)) return;
134  var xLineDiff = xAxis0.axisLine.GetWidth(m_Theme.axis.lineWidth);
135  var yLineDiff = yAxis0.axisLine.GetWidth(m_Theme.axis.lineWidth);
136  var xSplitDiff = xAxis0.splitLine.GetWidth(m_Theme.axis.splitLineWidth);
137  var ySplitDiff = yAxis0.splitLine.GetWidth(m_Theme.axis.splitLineWidth);
138  var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
139  var lp1 = new Vector3(m_ChartX, m_ChartY);
140  var lp2 = new Vector3(m_ChartX, m_ChartY + chartHeight);
141  var lp3 = new Vector3(grid.runtimeX - yLineDiff, m_ChartY + chartHeight);
142  var lp4 = new Vector3(grid.runtimeX - yLineDiff, m_ChartY);
143  UGL.DrawQuadrilateral(vh, lp1, lp2, lp3, lp4, backgroundColor);
144  var rp1 = new Vector3(grid.runtimeX + grid.runtimeWidth, m_ChartY);
145  var rp2 = new Vector3(grid.runtimeX + grid.runtimeWidth, m_ChartY + chartHeight);
146  var rp3 = new Vector3(m_ChartX + chartWidth, m_ChartY + chartHeight);
147  var rp4 = new Vector3(m_ChartX + chartWidth, m_ChartY);
148  UGL.DrawQuadrilateral(vh, rp1, rp2, rp3, rp4, backgroundColor);
149  var up1 = new Vector3(grid.runtimeX - yLineDiff, grid.runtimeY + grid.runtimeHeight + ySplitDiff);
150  var up2 = new Vector3(grid.runtimeX - yLineDiff, m_ChartY + chartHeight);
151  var up3 = new Vector3(grid.runtimeX + grid.runtimeWidth + xSplitDiff, m_ChartY + chartHeight);
152  var up4 = new Vector3(grid.runtimeX + grid.runtimeWidth + xSplitDiff,
153  grid.runtimeY + grid.runtimeHeight + ySplitDiff);
154  UGL.DrawQuadrilateral(vh, up1, up2, up3, up4, backgroundColor);
155  var dp1 = new Vector3(grid.runtimeX - yLineDiff, m_ChartY);
156  var dp2 = new Vector3(grid.runtimeX - yLineDiff, grid.runtimeY - xLineDiff);
157  var dp3 = new Vector3(grid.runtimeX + grid.runtimeWidth + xSplitDiff, grid.runtimeY - xLineDiff);
158  var dp4 = new Vector3(grid.runtimeX + grid.runtimeWidth + xSplitDiff, m_ChartY);
159  UGL.DrawQuadrilateral(vh, dp1, dp2, dp3, dp4, backgroundColor);
160  }
161 
162  protected override void DrawPainterSerie(VertexHelper vh, Serie serie)
163  {
164  base.DrawPainterSerie(vh, serie);
165  var colorIndex = m_LegendRealShowName.IndexOf(serie.legendName);
166  bool yCategory = IsAnyYAxisIsCategory();
167  switch (serie.type)
168  {
169  case SerieType.Line:
170  serie.dataPoints.Clear();
171  if (yCategory) DrawYLineSerie(vh, serie, colorIndex);
172  else DrawXLineSerie(vh, serie, colorIndex);
173  if (!SeriesHelper.IsStack(m_Series))
174  {
175  DrawLinePoint(vh, serie);
176  DrawLineArrow(vh, serie);
177  }
178  break;
179  case SerieType.Bar:
180  serie.dataPoints.Clear();
181  if (yCategory) DrawYBarSerie(vh, serie, colorIndex);
182  else DrawXBarSerie(vh, serie, colorIndex);
183  break;
184  case SerieType.Scatter:
185  case SerieType.EffectScatter:
186  serie.dataPoints.Clear();
187  DrawScatterSerie(vh, colorIndex, serie);
188  break;
189  case SerieType.Heatmap:
190  serie.dataPoints.Clear();
191  DrawHeatmapSerie(vh, colorIndex, serie);
192  break;
193  case SerieType.Candlestick:
194  serie.dataPoints.Clear();
195  DrawCandlestickSerie(vh, colorIndex, serie);
196  break;
197  }
198  }
199 
200  protected override void DrawPainterTop(VertexHelper vh)
201  {
202  DrawClip(vh);
203  if (SeriesHelper.IsAnyClipSerie(m_Series))
204  {
205  DrawCoordinate(vh);
206  }
207  DrawAxisTick(vh);
208  DrawLabelBackground(vh);
209  if (SeriesHelper.IsStack(m_Series))
210  {
211  foreach (var serie in m_Series.list)
212  {
213  DrawLinePoint(vh, serie);
214  DrawLineArrow(vh, serie);
215  }
216  }
217  bool yCategory = IsAnyYAxisIsCategory();
218  if (yCategory) DrawYTooltipIndicator(vh);
219  else DrawXTooltipIndicator(vh);
220  }
221 
222  protected override void CheckTootipArea(Vector2 local, bool isActivedOther)
223  {
224  if (isActivedOther)
225  {
226  foreach (var axis in m_XAxes) axis.SetTooltipLabelActive(false);
227  foreach (var axis in m_YAxes) axis.SetTooltipLabelActive(false);
228  return;
229  }
230  var grid = GetGrid(local);
231  if (grid == null)
232  {
233  tooltip.runtimeGridIndex = -1;
234  tooltip.ClearValue();
235  UpdateTooltip();
236  }
237  else
238  {
239  if (tooltip.runtimeGridIndex != grid.index)
240  {
241  tooltip.runtimeGridIndex = grid.index;
242  RefreshSeriePainterByGridIndex(grid.index);
243  }
244  UpdateTooltipValue(local);
245  }
246  if (tooltip.IsSelected())
247  {
248  tooltip.UpdateContentPos(local + tooltip.offset);
249  UpdateTooltip();
250  if (tooltip.IsDataIndexChanged() || tooltip.type == Tooltip.Type.Corss)
251  {
252  tooltip.UpdateLastDataIndex();
253  m_PainterTop.Refresh();
254  }
255  }
256  else if (tooltip.IsActive())
257  {
258  tooltip.SetActive(false);
259  m_PainterTop.Refresh();
260  }
261  }
262 
263  protected virtual void UpdateTooltipValue(Vector2 local)
264  {
265  var isCartesian = IsValue();
266  var grid = GetGrid(tooltip.runtimeGridIndex);
267  for (int i = 0; i < m_XAxes.Count; i++)
268  {
269  var xAxis = m_XAxes[i];
270  var yAxis = m_YAxes[i];
271  if (!xAxis.show && !yAxis.show) continue;
272  if (isCartesian && xAxis.show && yAxis.show)
273  {
274  var yRate = (yAxis.runtimeMaxValue - yAxis.runtimeMinValue) / grid.runtimeHeight;
275  var xRate = (xAxis.runtimeMaxValue - xAxis.runtimeMinValue) / grid.runtimeWidth;
276  var yValue = yRate * (local.y - grid.runtimeY - yAxis.runtimeZeroYOffset);
277  if (yAxis.runtimeMinValue > 0) yValue += yAxis.runtimeMinValue;
278  tooltip.runtimeYValues[i] = yValue;
279  var xValue = xRate * (local.x - grid.runtimeX - xAxis.runtimeZeroXOffset);
280  if (xAxis.runtimeMinValue > 0) xValue += xAxis.runtimeMinValue;
281  tooltip.runtimeXValues[i] = xValue;
282 
283  for (int j = 0; j < m_Series.Count; j++)
284  {
285  var serie = m_Series.GetSerie(j);
286  for (int n = 0; n < serie.data.Count; n++)
287  {
288  var serieData = serie.data[n];
289  var xdata = serieData.GetData(0, xAxis.inverse);
290  var ydata = serieData.GetData(1, yAxis.inverse);
291  var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
292  var symbolSize = symbol.GetSize(serieData == null ? null : serieData.data,
293  m_Theme.serie.lineSymbolSize);
294  if (Math.Abs(xValue - xdata) / xRate < symbolSize
295  && Math.Abs(yValue - ydata) / yRate < symbolSize)
296  {
297  tooltip.runtimeDataIndex[i] = n;
298  RefreshPainter(serie);
299  serieData.highlighted = true;
300  }
301  else
302  {
303  serieData.highlighted = false;
304  }
305  }
306  }
307  }
308  else if (IsCategory())
309  {
310  var dataZoomX = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
311  var dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoomX).Count : 0;
312  for (int j = 0; j < xAxis.GetDataNumber(dataZoomX); j++)
313  {
314  float splitWid = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, dataCount, dataZoomX);
315  float pX = grid.runtimeX + j * splitWid;
316  if ((xAxis.boundaryGap && (local.x > pX && local.x <= pX + splitWid)) ||
317  (!xAxis.boundaryGap && (local.x > pX - splitWid / 2 && local.x <= pX + splitWid / 2)))
318  {
319  tooltip.runtimeXValues[i] = j;
320  tooltip.runtimeDataIndex[i] = j;
321  break;
322  }
323  }
324  var dataZoomY = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
325  dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoomY).Count : 0;
326  for (int j = 0; j < yAxis.GetDataNumber(dataZoomY); j++)
327  {
328  float splitWid = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, dataCount, dataZoomY);
329  float pY = grid.runtimeY + j * splitWid;
330  if ((yAxis.boundaryGap && (local.y > pY && local.y <= pY + splitWid)) ||
331  (!yAxis.boundaryGap && (local.y > pY - splitWid / 2 && local.y <= pY + splitWid / 2)))
332  {
333  tooltip.runtimeYValues[i] = j;
334  break;
335  }
336  }
337  }
338  else if (xAxis.IsCategory())
339  {
340  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
341  var dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoom).Count : 0;
342  var value = (yAxis.runtimeMaxValue - yAxis.runtimeMinValue) * (local.y - grid.runtimeY - yAxis.runtimeZeroYOffset) / grid.runtimeHeight;
343  if (yAxis.runtimeMinValue > 0) value += yAxis.runtimeMinValue;
344  tooltip.runtimeYValues[i] = value;
345  for (int j = 0; j < xAxis.GetDataNumber(dataZoom); j++)
346  {
347  float splitWid = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, dataCount, dataZoom);
348  float pX = grid.runtimeX + j * splitWid;
349  if ((xAxis.boundaryGap && (local.x > pX && local.x <= pX + splitWid)) ||
350  (!xAxis.boundaryGap && (local.x > pX - splitWid / 2 && local.x <= pX + splitWid / 2)))
351  {
352  tooltip.runtimeXValues[i] = j;
353  tooltip.runtimeDataIndex[i] = j;
354  RefreshSeriePainterByAxisIndex(xAxis);
355  break;
356  }
357  }
358  }
359  else if (yAxis.IsCategory())
360  {
361  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
362  var dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoom).Count : 0;
363  var value = (xAxis.runtimeMaxValue - xAxis.runtimeMinValue) * (local.x - grid.runtimeX - xAxis.runtimeZeroXOffset) / grid.runtimeWidth;
364  if (xAxis.runtimeMinValue > 0) value += xAxis.runtimeMinValue;
365  tooltip.runtimeXValues[i] = value;
366  for (int j = 0; j < yAxis.GetDataNumber(dataZoom); j++)
367  {
368  float splitWid = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, dataCount, dataZoom);
369  float pY = grid.runtimeY + j * splitWid;
370  if ((yAxis.boundaryGap && (local.y > pY && local.y <= pY + splitWid)) ||
371  (!yAxis.boundaryGap && (local.y > pY - splitWid / 2 && local.y <= pY + splitWid / 2)))
372  {
373  tooltip.runtimeYValues[i] = j;
374  tooltip.runtimeDataIndex[i] = j;
375  RefreshSeriePainterByAxisIndex(yAxis);
376  break;
377  }
378  }
379  }
380  }
381  }
382 
383  protected StringBuilder sb = new StringBuilder(100);
384  protected override void UpdateTooltip()
385  {
386  base.UpdateTooltip();
387  int index;
388  Axis tempAxis;
389  bool isCartesian = IsValue();
390  if (isCartesian)
391  {
392  index = tooltip.runtimeDataIndex[0];
393  tempAxis = m_XAxes[0];
394  }
395  else if (m_XAxes[0].type == Axis.AxisType.Value)
396  {
397  index = (int)tooltip.runtimeYValues[0];
398  tempAxis = m_YAxes[0];
399  }
400  else
401  {
402  index = (int)tooltip.runtimeXValues[0];
403  tempAxis = m_XAxes[0];
404  }
405  if (index < 0)
406  {
407  if (tooltip.IsActive())
408  {
409  tooltip.SetActive(false);
410  RefreshChart();
411  }
412  return;
413  }
414  UpdateSerieGridIndex();
415  RefreshSeriePainterByGridIndex(grid.index);
416  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(tempAxis, dataZooms);
417  var content = TooltipHelper.GetFormatterContent(tooltip, index, this, dataZoom, isCartesian);
418  TooltipHelper.SetContentAndPosition(tooltip, content, chartRect);
419  tooltip.SetActive(true);
420 
421  for (int i = 0; i < m_XAxes.Count; i++)
422  {
423  UpdateAxisTooltipLabel(i, m_XAxes[i]);
424  }
425  for (int i = 0; i < m_YAxes.Count; i++)
426  {
427  UpdateAxisTooltipLabel(i, m_YAxes[i]);
428  }
429  }
430 
431  internal string GetTooltipCategory(int dataIndex, DataZoom dataZoom = null)
432  {
433  bool isCartesian = IsValue();
434  var index = -1;
435  Axis tempAxis;
436  if (isCartesian)
437  {
438  index = tooltip.runtimeDataIndex[0];
439  tempAxis = m_XAxes[0];
440  }
441  else if (m_XAxes[0].type == Axis.AxisType.Value)
442  {
443  index = (int)tooltip.runtimeYValues[0];
444  tempAxis = m_YAxes[0];
445  }
446  else
447  {
448  index = (int)tooltip.runtimeXValues[0];
449  tempAxis = m_XAxes[0];
450  }
451  return tempAxis.GetData(index, dataZoom);
452  }
453  internal string GetTooltipCategory(int dataIndex, Serie serie, DataZoom dataZoom = null)
454  {
455  bool isCartesian = IsValue();
456  var index = -1;
457  Axis tempAxis;
458  if (isCartesian)
459  {
460  index = tooltip.runtimeDataIndex[0];
461  tempAxis = GetXAxis(serie.xAxisIndex);
462  }
463  else if (m_XAxes[0].type == Axis.AxisType.Value)
464  {
465  index = (int)tooltip.runtimeYValues[0];
466  tempAxis = GetYAxis(serie.yAxisIndex);
467  }
468  else
469  {
470  index = (int)tooltip.runtimeXValues[0];
471  tempAxis = GetXAxis(serie.xAxisIndex);
472  }
473  return tempAxis == null ? "" : tempAxis.GetData(index, dataZoom);
474  }
475 
476  protected void UpdateAxisTooltipLabel(int axisIndex, Axis axis)
477  {
478  var showTooltipLabel = axis.show && tooltip.type == Tooltip.Type.Corss;
479  axis.SetTooltipLabelActive(showTooltipLabel);
480  if (!showTooltipLabel) return;
481  var labelText = "";
482  var labelPos = Vector2.zero;
483  var grid = GetAxisGridOrDefault(axis);
484  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(axis, dataZooms);
485  if (axis is XAxis)
486  {
487  var posY = axisIndex > 0 ? grid.runtimeY + grid.runtimeHeight : grid.runtimeY;
488  var diff = axisIndex > 0
489  ? -axis.axisLabel.textStyle.GetFontSize(m_Theme.tooltip) - axis.axisLabel.margin - 3.5f
490  : axis.axisLabel.margin / 2 + 1;
491  if (axis.IsValue())
492  {
493  labelText = ChartCached.NumberToStr(tooltip.runtimeXValues[axisIndex], axis.axisLabel.numericFormatter);
494  labelPos = new Vector2(tooltip.runtimePointerPos.x, posY - diff);
495  }
496  else
497  {
498  labelText = axis.GetData((int)tooltip.runtimeXValues[axisIndex], dataZoom);
499  var splitWidth = AxisHelper.GetDataWidth(axis, grid.runtimeWidth, 0, dataZoom);
500  var index = (int)tooltip.runtimeXValues[axisIndex];
501  var px = grid.runtimeX + index * splitWidth + (axis.boundaryGap ? splitWidth / 2 : 0);
502  labelPos = new Vector2(px, posY - diff);
503  }
504  }
505  else if (axis is YAxis)
506  {
507  var posX = axisIndex > 0 ? grid.runtimeX + grid.runtimeWidth : grid.runtimeX;
508  var diff = axisIndex > 0 ? -axis.axisLabel.margin + 3 : axis.axisLabel.margin - 3;
509  if (axis.IsValue())
510  {
511  labelText = ChartCached.NumberToStr(tooltip.runtimeYValues[axisIndex], axis.axisLabel.numericFormatter);
512  labelPos = new Vector2(posX - diff, tooltip.runtimePointerPos.y);
513  }
514  else
515  {
516  labelText = axis.GetData((int)tooltip.runtimeYValues[axisIndex], dataZoom);
517  var splitWidth = AxisHelper.GetDataWidth(axis, grid.runtimeHeight, 0, dataZoom);
518  var index = (int)tooltip.runtimeYValues[axisIndex];
519  var py = grid.runtimeY + index * splitWidth + (axis.boundaryGap ? splitWidth / 2 : 0);
520  labelPos = new Vector2(posX - diff, py);
521  }
522  }
523  axis.UpdateTooptipLabelText(labelText);
524  axis.UpdateTooltipLabelPos(labelPos);
525  }
526 
527  private void InitDefaultAxes()
528  {
529  if (m_XAxes.Count <= 0)
530  {
531  var axis1 = XAxis.defaultXAxis;
532  var axis2 = XAxis.defaultXAxis;
533  axis1.show = true;
534  axis2.show = false;
535  axis1.position = Axis.AxisPosition.Bottom;
536  axis2.position = Axis.AxisPosition.Top;
537  m_XAxes.Add(axis1);
538  m_XAxes.Add(axis2);
539  }
540  if (m_YAxes.Count <= 0)
541  {
542  var axis1 = YAxis.defaultYAxis;
543  var axis2 = YAxis.defaultYAxis;
544  axis1.show = true;
545  axis1.splitNumber = 5;
546  axis1.boundaryGap = false;
547  axis2.show = false;
548  axis1.position = Axis.AxisPosition.Left;
549  axis2.position = Axis.AxisPosition.Right;
550  m_YAxes.Add(axis1);
551  m_YAxes.Add(axis2);
552  }
553  foreach (var axis in m_XAxes) axis.runtimeMinValue = axis.runtimeMaxValue = 0;
554  foreach (var axis in m_YAxes) axis.runtimeMinValue = axis.runtimeMaxValue = 0;
555  }
556 
557  private void InitAxisY()
558  {
559  for (int i = 0; i < m_YAxes.Count; i++)
560  {
561  InitYAxis(i, m_YAxes[i]);
562  }
563  }
564 
565  private void InitYAxis(int yAxisIndex, YAxis yAxis)
566  {
567  yAxis.painter = m_Painter;
568  yAxis.refreshComponent = delegate ()
569  {
570  InitAxisRuntimeData(yAxis);
571  string objName = ChartCached.GetYAxisName(yAxisIndex);
572  var axisObj = ChartHelper.AddObject(objName, transform, graphAnchorMin,
573  graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
574  yAxis.gameObject = axisObj;
575  yAxis.runtimeAxisLabelList.Clear();
576  axisObj.SetActive(yAxis.show);
577  axisObj.hideFlags = chartHideFlags;
578  ChartHelper.HideAllObject(axisObj);
579  var grid = GetAxisGridOrDefault(yAxis);
580  if (grid == null) return;
581  if (!yAxis.show) return;
582  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
583  var axisLabelTextStyle = yAxis.axisLabel.textStyle;
584  int splitNumber = AxisHelper.GetScaleNumber(yAxis, grid.runtimeHeight, dataZoom);
585  float totalWidth = 0;
586  float eachWidth = AxisHelper.GetEachWidth(yAxis, grid.runtimeHeight, dataZoom);
587  float gapWidth = yAxis.boundaryGap ? eachWidth / 2 : 0;
588  float textWidth = yAxis.axisLabel.width > 0
589  ? yAxis.axisLabel.width
590  : grid.left;
591  float textHeight = yAxis.axisLabel.height > 0
592  ? yAxis.axisLabel.height
593  : 20f;
594  if (yAxis.IsCategory() && yAxis.boundaryGap)
595  {
596  splitNumber -= 1;
597  }
598  for (int i = 0; i < splitNumber; i++)
599  {
600  ChartLabel txt;
601  var inside = yAxis.axisLabel.inside;
602  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
603  var labelName = AxisHelper.GetLabelName(yAxis, grid.runtimeHeight, i, yAxis.runtimeMinValue,
604  yAxis.runtimeMaxValue, dataZoom, isPercentStack);
605  if ((inside && yAxis.IsLeft()) || (!inside && yAxis.IsRight()))
606  {
607  txt = ChartHelper.AddAxisLabelObject(splitNumber, i, objName + i, axisObj.transform, Vector2.zero,
608  Vector2.zero, new Vector2(0, 0.5f), new Vector2(textWidth, textHeight), yAxis, theme.axis,
609  labelName);
610  txt.label.SetAlignment(axisLabelTextStyle.GetAlignment(TextAnchor.MiddleLeft));
611  }
612  else
613  {
614  txt = ChartHelper.AddAxisLabelObject(splitNumber, i, objName + i, axisObj.transform, Vector2.zero,
615  Vector2.zero, new Vector2(1, 0.5f), new Vector2(textWidth, textHeight), yAxis, theme.axis,
616  labelName);
617  txt.label.SetAlignment(axisLabelTextStyle.GetAlignment(TextAnchor.MiddleRight));
618  }
619  var labelWidth = AxisHelper.GetScaleWidth(yAxis, grid.runtimeHeight, i + 1, dataZoom);
620  if (i == 0) yAxis.axisLabel.SetRelatedText(txt.label, labelWidth);
621  txt.SetPosition(GetLabelYPosition(totalWidth + gapWidth, i, yAxisIndex, yAxis));
622  yAxis.runtimeAxisLabelList.Add(txt);
623  totalWidth += labelWidth;
624  }
625  if (yAxis.axisName.show)
626  {
627  var axisNameTextStyle = yAxis.axisName.textStyle;
628  var offset = axisNameTextStyle.offset;
629  ChartText axisName = null;
630  var xAxis = GetXAxis(yAxisIndex);
631  var zeroPos = new Vector3(grid.runtimeX + (xAxis == null ? 0 : xAxis.runtimeZeroXOffset), grid.runtimeY);
632  switch (yAxis.axisName.location)
633  {
634  case AxisName.Location.Start:
635  axisName = ChartHelper.AddTextObject(s_DefaultAxisName, axisObj.transform, new Vector2(0.5f, 0.5f),
636  new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100, 20), axisNameTextStyle,
637  m_Theme.axis);
638  axisName.SetAlignment(axisNameTextStyle.GetAlignment(TextAnchor.MiddleCenter));
639  axisName.SetLocalPosition(yAxis.position == Axis.AxisPosition.Right ?
640  new Vector2(grid.runtimeX + grid.runtimeWidth + offset.x + yAxis.offset, grid.runtimeY - offset.y) :
641  new Vector2(zeroPos.x + offset.x + yAxis.offset, grid.runtimeY - offset.y));
642  break;
643  case AxisName.Location.Middle:
644  axisName = ChartHelper.AddTextObject(s_DefaultAxisName, axisObj.transform, new Vector2(1, 0.5f),
645  new Vector2(1, 0.5f), new Vector2(1, 0.5f), new Vector2(100, 20), axisNameTextStyle,
646  m_Theme.axis);
647  axisName.SetAlignment(axisNameTextStyle.GetAlignment(TextAnchor.MiddleRight));
648  axisName.SetLocalPosition(yAxis.position == Axis.AxisPosition.Right ?
649  new Vector2(grid.runtimeX + grid.runtimeWidth - offset.x + yAxis.offset, grid.runtimeY + grid.runtimeHeight / 2 + offset.y) :
650  new Vector2(grid.runtimeX - offset.x + yAxis.offset, grid.runtimeY + grid.runtimeHeight / 2 + offset.y));
651  break;
652  case AxisName.Location.End:
653  axisName = ChartHelper.AddTextObject(s_DefaultAxisName, axisObj.transform, new Vector2(0.5f, 0.5f),
654  new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100, 20), axisNameTextStyle,
655  m_Theme.axis);
656  axisName.SetAlignment(axisNameTextStyle.GetAlignment(TextAnchor.MiddleCenter));
657  axisName.SetLocalPosition(yAxis.position == Axis.AxisPosition.Right ?
658  new Vector2(grid.runtimeX + grid.runtimeWidth + offset.x + yAxis.offset, grid.runtimeY + grid.runtimeHeight + offset.y) :
659  new Vector2(zeroPos.x + offset.x + yAxis.offset, grid.runtimeY + grid.runtimeHeight + offset.y));
660  break;
661  }
662  axisName.SetText(yAxis.axisName.name);
663  }
664  //init tooltip label
665  if (tooltip.runtimeGameObject)
666  {
667  Vector2 privot = yAxis.position == Axis.AxisPosition.Right ? new Vector2(0, 0.5f) : new Vector2(1, 0.5f);
668  var labelParent = tooltip.runtimeGameObject.transform;
669  var labelName = ChartCached.GetAxisTooltipLabel(objName);
670  GameObject labelObj = ChartHelper.AddTooltipLabel(labelName, labelParent, m_Theme, privot);
671  yAxis.SetTooltipLabel(labelObj);
672  yAxis.SetTooltipLabelColor(m_Theme.tooltip.labelBackgroundColor, m_Theme.tooltip.labelTextColor);
673  yAxis.SetTooltipLabelActive(yAxis.show && tooltip.show && tooltip.type == Tooltip.Type.Corss);
674  }
675  };
676  yAxis.refreshComponent();
677  }
678 
679  protected virtual void InitAxisRuntimeData(Axis axis)
680  {
681  }
682 
683  internal void InitAxisX()
684  {
685  for (int i = 0; i < m_XAxes.Count; i++)
686  {
687  InitXAxis(i, m_XAxes[i]);
688  }
689  }
690 
691  private void InitXAxis(int xAxisIndex, XAxis xAxis)
692  {
693  xAxis.painter = m_Painter;
694  xAxis.refreshComponent = delegate ()
695  {
696  string objName = ChartCached.GetXAxisName(xAxisIndex);
697  var axisObj = ChartHelper.AddObject(objName, transform, graphAnchorMin,
698  graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
699  xAxis.gameObject = axisObj;
700  xAxis.runtimeAxisLabelList.Clear();
701  axisObj.SetActive(xAxis.show);
702  axisObj.hideFlags = chartHideFlags;
703  ChartHelper.HideAllObject(axisObj);
704  var grid = GetAxisGridOrDefault(xAxis);
705  if (grid == null) return;
706  if (!xAxis.show) return;
707  var axisLabelTextStyle = xAxis.axisLabel.textStyle;
708  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
709  int splitNumber = AxisHelper.GetScaleNumber(xAxis, grid.runtimeWidth, dataZoom);
710  float totalWidth = 0;
711  float eachWidth = AxisHelper.GetEachWidth(xAxis, grid.runtimeWidth, dataZoom);
712  float gapWidth = xAxis.boundaryGap ? eachWidth / 2 : 0;
713  float textWidth = xAxis.axisLabel.width > 0
714  ? xAxis.axisLabel.width
715  : AxisHelper.GetScaleWidth(xAxis, grid.runtimeWidth, 0, dataZoom);
716  float textHeight = xAxis.axisLabel.height > 0
717  ? xAxis.axisLabel.height
718  : 20f;
719  if (xAxis.IsCategory() && xAxis.boundaryGap)
720  {
721  splitNumber -= 1;
722  }
723  for (int i = 0; i < splitNumber; i++)
724  {
725  var labelWidth = AxisHelper.GetScaleWidth(xAxis, grid.runtimeWidth, i + 1, dataZoom);
726  var inside = xAxis.axisLabel.inside;
727  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
728  var labelName = AxisHelper.GetLabelName(xAxis, grid.runtimeWidth, i, xAxis.runtimeMinValue,
729  xAxis.runtimeMaxValue, dataZoom, isPercentStack);
730  var label = ChartHelper.AddAxisLabelObject(splitNumber, i, ChartCached.GetXAxisName(xAxisIndex, i),
731  axisObj.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
732  new Vector2(textWidth, textHeight), xAxis, theme.axis, labelName);
733 
734  if (i == 0) xAxis.axisLabel.SetRelatedText(label.label, labelWidth);
735  label.label.SetAlignment(axisLabelTextStyle.GetAlignment(TextAnchor.MiddleCenter));
736  label.SetPosition(GetLabelXPosition(totalWidth + gapWidth, i, xAxisIndex, xAxis));
737  xAxis.runtimeAxisLabelList.Add(label);
738  totalWidth += labelWidth;
739  }
740  if (xAxis.axisName.show)
741  {
742  var axisNameTextStyle = xAxis.axisName.textStyle;
743  var offset = axisNameTextStyle.offset;
744  ChartText axisName = null;
745  var yAxis = GetYAxis(xAxisIndex);
746  var zeroPos = new Vector3(grid.runtimeX, grid.runtimeY + (yAxis == null ? 0 : yAxis.runtimeZeroYOffset));
747  switch (xAxis.axisName.location)
748  {
749  case AxisName.Location.Start:
750  axisName = ChartHelper.AddTextObject(s_DefaultAxisName, axisObj.transform, new Vector2(1, 0.5f),
751  new Vector2(1, 0.5f), new Vector2(1, 0.5f), new Vector2(100, 20), axisNameTextStyle, theme.axis);
752  axisName.SetAlignment(axisNameTextStyle.GetAlignment(TextAnchor.MiddleRight));
753  axisName.SetLocalPosition(xAxis.position == Axis.AxisPosition.Top ?
754  new Vector2(zeroPos.x - offset.x, grid.runtimeY + grid.runtimeHeight + offset.y + xAxis.offset) :
755  new Vector2(zeroPos.x - offset.x, zeroPos.y + offset.y + xAxis.offset));
756  break;
757  case AxisName.Location.Middle:
758  axisName = ChartHelper.AddTextObject(s_DefaultAxisName, axisObj.transform, new Vector2(0.5f, 0.5f),
759  new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(100, 20), axisNameTextStyle, theme.axis);
760  axisName.SetAlignment(axisNameTextStyle.GetAlignment(TextAnchor.MiddleCenter));
761  axisName.SetLocalPosition(xAxis.position == Axis.AxisPosition.Top ?
762  new Vector2(grid.runtimeX + grid.runtimeWidth / 2 + offset.x, grid.runtimeY + grid.runtimeHeight - offset.y + xAxis.offset) :
763  new Vector2(grid.runtimeX + grid.runtimeWidth / 2 + offset.x, grid.runtimeY - offset.y + xAxis.offset));
764  break;
765  case AxisName.Location.End:
766  axisName = ChartHelper.AddTextObject(s_DefaultAxisName, axisObj.transform, new Vector2(0, 0.5f),
767  new Vector2(0, 0.5f), new Vector2(0, 0.5f), new Vector2(100, 20), axisNameTextStyle, theme.axis);
768  axisName.SetAlignment(axisNameTextStyle.GetAlignment(TextAnchor.MiddleLeft));
769  axisName.SetLocalPosition(xAxis.position == Axis.AxisPosition.Top ?
770  new Vector2(grid.runtimeX + grid.runtimeWidth + offset.x, grid.runtimeY + grid.runtimeHeight + offset.y + xAxis.offset) :
771  new Vector2(grid.runtimeX + grid.runtimeWidth + offset.x, zeroPos.y + offset.y + xAxis.offset));
772  break;
773  }
774  axisName.SetText(xAxis.axisName.name);
775  }
776  if (tooltip.runtimeGameObject)
777  {
778  Vector2 privot = xAxis.position != Axis.AxisPosition.Top ? new Vector2(0.5f, 1) : new Vector2(0.5f, 1);
779  var labelParent = tooltip.runtimeGameObject.transform;
780  var labelName = ChartCached.GetAxisTooltipLabel(objName);
781  GameObject labelObj = ChartHelper.AddTooltipLabel(labelName, labelParent, theme, privot);
782  xAxis.SetTooltipLabel(labelObj);
783  xAxis.SetTooltipLabelColor(theme.tooltip.labelBackgroundColor, theme.tooltip.labelTextColor);
784  xAxis.SetTooltipLabelActive(xAxis.show && tooltip.show && tooltip.type == Tooltip.Type.Corss);
785  }
786  };
787  xAxis.refreshComponent();
788  }
789 
790  private void InitGrid()
791  {
792  for (int i = 0; i < m_Grids.Count; i++)
793  {
794  var grid = m_Grids[i];
795  grid.index = i;
796  grid.painter = m_Painter;
797  grid.refreshComponent = delegate ()
798  {
799  OnCoordinateChanged();
800  };
801  grid.refreshComponent();
802  }
803  }
804 
805  private void InitDataZoom()
806  {
807  for (int i = 0; i < m_DataZooms.Count; i++)
808  {
809  var dataZoom = m_DataZooms[i];
810  dataZoom.index = i;
811  dataZoom.painter = m_PainterTop;
812  dataZoom.refreshComponent = delegate ()
813  {
814  var dataZoomObject = ChartHelper.AddObject(s_DefaultDataZoom + dataZoom.index, transform, graphAnchorMin,
815  graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
816  dataZoom.gameObject = dataZoomObject;
817  dataZoomObject.hideFlags = chartHideFlags;
818  ChartHelper.HideAllObject(dataZoomObject);
819  var startLabel = ChartHelper.AddTextObject(s_DefaultDataZoom + "start", dataZoomObject.transform,
820  Vector2.zero, Vector2.zero, new Vector2(1, 0.5f), new Vector2(200, 20), dataZoom.textStyle,
821  m_Theme.dataZoom);
822  startLabel.SetAlignment(TextAnchor.MiddleRight);
823  var endLabel = ChartHelper.AddTextObject(s_DefaultDataZoom + "end", dataZoomObject.transform,
824  Vector2.zero, Vector2.zero, new Vector2(0, 0.5f), new Vector2(200, 20), dataZoom.textStyle,
825  m_Theme.dataZoom);
826  endLabel.SetAlignment(TextAnchor.MiddleLeft);
827  dataZoom.SetStartLabel(startLabel);
828  dataZoom.SetEndLabel(endLabel);
829  dataZoom.SetLabelActive(false);
830  CheckRaycastTarget();
831  foreach (var index in dataZoom.xAxisIndexs)
832  {
833  var xAxis = m_XAxes[index];
834  if (xAxis != null)
835  {
836  xAxis.UpdateFilterData(dataZoom);
837  }
838  }
839  if (m_Series != null)
840  {
841  m_Series.UpdateFilterData(dataZoom);
842  }
843  };
844  dataZoom.refreshComponent();
845  }
846  }
847 
848  private Vector3 GetLabelYPosition(float scaleWid, int i, int yAxisIndex, YAxis yAxis)
849  {
850  var grid = GetAxisGridOrDefault(yAxis);
851  var startX = yAxis.IsLeft() ? grid.runtimeX : grid.runtimeX + grid.runtimeWidth;
852  var posX = 0f;
853  var inside = yAxis.axisLabel.inside;
854  if ((inside && yAxis.IsLeft()) || (!inside && yAxis.IsRight()))
855  {
856  posX = startX + yAxis.axisLabel.margin;
857  }
858  else
859  {
860  posX = startX - yAxis.axisLabel.margin;
861  }
862  posX += yAxis.offset;
863  return new Vector3(posX, grid.runtimeY + scaleWid, 0) + yAxis.axisLabel.textStyle.offsetv3;
864  }
865 
866  private Vector3 GetLabelXPosition(float scaleWid, int i, int xAxisIndex, XAxis xAxis)
867  {
868  var grid = GetAxisGridOrDefault(xAxis);
869  var startY = grid.runtimeY + (xAxis.axisLabel.onZero ? m_YAxes[xAxisIndex].runtimeZeroYOffset : 0);
870  if (xAxis.IsTop()) startY += grid.runtimeHeight;
871  var posY = 0f;
872  var inside = xAxis.axisLabel.inside;
873  var fontSize = xAxis.axisLabel.textStyle.GetFontSize(m_Theme.axis);
874  if ((inside && xAxis.IsBottom()) || (!inside && xAxis.IsTop()))
875  {
876  posY = startY + xAxis.axisLabel.margin + fontSize / 2;
877  }
878  else
879  {
880  posY = startY - xAxis.axisLabel.margin - fontSize / 2;
881  }
882  posY += xAxis.offset;
883  return new Vector3(grid.runtimeX + scaleWid, posY) + xAxis.axisLabel.textStyle.offsetv3;
884  }
885 
886  protected virtual void CheckMinMaxValue()
887  {
888  if (m_XAxes == null || m_YAxes == null) return;
889  for (int i = 0; i < m_XAxes.Count; i++)
890  {
891  UpdateAxisMinMaxValue(i, m_XAxes[i]);
892  }
893  for (int i = 0; i < m_YAxes.Count; i++)
894  {
895  UpdateAxisMinMaxValue(i, m_YAxes[i]);
896  }
897  }
898 
899  private void UpdateAxisMinMaxValue(int axisIndex, Axis axis, bool updateChart = true)
900  {
901  if (!axis.show) return;
902  if (axis.IsCategory())
903  {
904  axis.runtimeMinValue = 0;
905  axis.runtimeMaxValue = SeriesHelper.GetMaxSerieDataCount(m_Series) - 1;
906  return;
907  }
908  double tempMinValue = 0;
909  double tempMaxValue = 0;
910  GetSeriesMinMaxValue(axis, axisIndex, out tempMinValue, out tempMaxValue);
911  if (tempMinValue != axis.runtimeMinValue || tempMaxValue != axis.runtimeMaxValue)
912  {
913  m_IsPlayingAnimation = true;
914  var needCheck = !m_IsPlayingAnimation && axis.runtimeLastCheckInverse == axis.inverse;
915  axis.UpdateMinValue(tempMinValue, needCheck);
916  axis.UpdateMaxValue(tempMaxValue, needCheck);
917  axis.runtimeZeroXOffset = 0;
918  axis.runtimeZeroYOffset = 0;
919  axis.runtimeLastCheckInverse = axis.inverse;
920  if (tempMinValue != 0 || tempMaxValue != 0)
921  {
922  var grid = GetAxisGridOrDefault(axis);
923  if (grid != null && axis is XAxis && axis.IsValue())
924  {
925  axis.runtimeZeroXOffset = axis.runtimeMinValue > 0 ? 0 :
926  axis.runtimeMaxValue < 0 ? grid.runtimeWidth :
927  (float)(Math.Abs(axis.runtimeMinValue) * (grid.runtimeWidth / (Math.Abs(axis.runtimeMinValue) + Math.Abs(axis.runtimeMaxValue))));
928  }
929  if (grid != null && axis is YAxis && axis.IsValue())
930  {
931  axis.runtimeZeroYOffset = axis.runtimeMinValue > 0 ? 0 :
932  axis.runtimeMaxValue < 0 ? grid.runtimeHeight :
933  (float)(Math.Abs(axis.runtimeMinValue) * (grid.runtimeHeight / (Math.Abs(axis.runtimeMinValue) + Math.Abs(axis.runtimeMaxValue))));
934  }
935  }
936  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(axis, dataZooms);
937  if (dataZoom != null && dataZoom.enable)
938  {
939  if (axis is XAxis) dataZoom.SetXAxisIndexValueInfo(axisIndex, tempMinValue, tempMaxValue);
940  else dataZoom.SetYAxisIndexValueInfo(axisIndex, tempMinValue, tempMaxValue);
941  }
942  if (updateChart)
943  {
944  UpdateAxisLabelText(axis);
945  RefreshChart();
946  }
947  }
948  if (axis.IsValueChanging(500) && !m_IsPlayingAnimation)
949  {
950  UpdateAxisLabelText(axis);
951  RefreshChart();
952  }
953  }
954 
955  protected virtual void GetSeriesMinMaxValue(Axis axis, int axisIndex, out double tempMinValue, out double tempMaxValue)
956  {
957  if (IsValue())
958  {
959  if (axis is XAxis)
960  {
961  SeriesHelper.GetXMinMaxValue(m_Series, null, axisIndex, true, axis.inverse, out tempMinValue, out tempMaxValue);
962  }
963  else
964  {
965  SeriesHelper.GetYMinMaxValue(m_Series, null, axisIndex, true, axis.inverse, out tempMinValue, out tempMaxValue);
966  }
967  }
968  else
969  {
970  SeriesHelper.GetYMinMaxValue(m_Series, null, axisIndex, false, axis.inverse, out tempMinValue, out tempMaxValue);
971  }
972  AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true);
973  }
974 
975  protected void UpdateAxisLabelText(Axis axis)
976  {
977  var grid = GetAxisGridOrDefault(axis);
978  if (grid == null || axis == null) return;
979  float runtimeWidth = axis is XAxis ? grid.runtimeWidth : grid.runtimeHeight;
980  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
981  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(axis, dataZooms);
982  axis.UpdateLabelText(runtimeWidth, dataZoom, isPercentStack, 500);
983  }
984 
985  protected virtual void OnCoordinateChanged()
986  {
988  for (int i = 0; i < m_XAxes.Count; i++)
989  {
990  m_XAxes[i].SetAllDirty();
991  }
992  for (int i = 0; i < m_YAxes.Count; i++)
993  {
994  m_YAxes[i].SetAllDirty();
995  }
996  }
997 
998  protected override void OnSizeChanged()
999  {
1000  base.OnSizeChanged();
1001  OnCoordinateChanged();
1002  }
1003 
1004  private void DrawCoordinate(VertexHelper vh)
1005  {
1006  DrawGrid(vh);
1007  for (int i = 0; i < m_XAxes.Count; i++)
1008  {
1009  m_XAxes[i].index = i;
1010  DrawXAxisSplit(vh, i, m_XAxes[i]);
1011  }
1012  for (int i = 0; i < m_YAxes.Count; i++)
1013  {
1014  m_YAxes[i].index = i;
1015  DrawYAxisSplit(vh, i, m_YAxes[i]);
1016  }
1017  for (int i = 0; i < m_XAxes.Count; i++)
1018  {
1019  DrawXAxisLine(vh, i, m_XAxes[i]);
1020  }
1021  for (int i = 0; i < m_YAxes.Count; i++)
1022  {
1023  DrawYAxisLine(vh, i, m_YAxes[i]);
1024  }
1025  }
1026 
1027  private void DrawAxisTick(VertexHelper vh)
1028  {
1029  for (int i = 0; i < m_XAxes.Count; i++)
1030  {
1031  DrawXAxisTick(vh, i, m_XAxes[i]);
1032  }
1033  for (int i = 0; i < m_YAxes.Count; i++)
1034  {
1035  DrawYAxisTick(vh, i, m_YAxes[i]);
1036  }
1037  }
1038 
1039  private void DrawGrid(VertexHelper vh)
1040  {
1041  foreach (var grid in m_Grids)
1042  {
1043  if (grid.show && !ChartHelper.IsClearColor(grid.backgroundColor))
1044  {
1045  var p1 = new Vector2(grid.runtimeX, grid.runtimeY);
1046  var p2 = new Vector2(grid.runtimeX, grid.runtimeY + grid.runtimeHeight);
1047  var p3 = new Vector2(grid.runtimeX + grid.runtimeWidth, grid.runtimeY + grid.runtimeHeight);
1048  var p4 = new Vector2(grid.runtimeX + grid.runtimeWidth, grid.runtimeY);
1049  UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, grid.backgroundColor);
1050  }
1051  }
1052  }
1053 
1054  private void DrawYAxisSplit(VertexHelper vh, int yAxisIndex, YAxis yAxis)
1055  {
1056  if (AxisHelper.NeedShowSplit(yAxis))
1057  {
1058  var grid = GetAxisGridOrDefault(yAxis);
1059  if (grid == null) return;
1060  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
1061  var size = AxisHelper.GetScaleNumber(yAxis, grid.runtimeWidth, dataZoom);
1062  var totalWidth = grid.runtimeY;
1063  var xAxis = GetRelatedXAxis(yAxis);
1064  var zeroPos = new Vector3(grid.runtimeX + xAxis.runtimeZeroXOffset, grid.runtimeY + yAxis.runtimeZeroYOffset);
1065  var lineColor = yAxis.splitLine.GetColor(m_Theme.axis.splitLineColor);
1066  var lineWidth = yAxis.splitLine.GetWidth(m_Theme.axis.lineWidth);
1067  var lineType = yAxis.splitLine.GetType(m_Theme.axis.splitLineType);
1068  for (int i = 0; i < size; i++)
1069  {
1070  var scaleWidth = AxisHelper.GetScaleWidth(yAxis, grid.runtimeHeight, i + 1, dataZoom);
1071  float pY = totalWidth;
1072  if (yAxis.boundaryGap && yAxis.axisTick.alignWithLabel)
1073  {
1074  pY -= scaleWidth / 2;
1075  }
1076  if (yAxis.splitArea.show && i < size - 1)
1077  {
1078  UGL.DrawQuadrilateral(vh, new Vector2(grid.runtimeX, pY),
1079  new Vector2(grid.runtimeX + grid.runtimeWidth, pY),
1080  new Vector2(grid.runtimeX + grid.runtimeWidth, pY + scaleWidth),
1081  new Vector2(grid.runtimeX, pY + scaleWidth),
1082  yAxis.splitArea.GetColor(i, m_Theme.axis));
1083  }
1084  if (yAxis.splitLine.show)
1085  {
1086  if (!xAxis.axisLine.show || !xAxis.axisLine.onZero || zeroPos.y != pY)
1087  {
1088  if (yAxis.splitLine.NeedShow(i))
1089  {
1090  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, new Vector3(grid.runtimeX, pY),
1091  new Vector3(grid.runtimeX + grid.runtimeWidth, pY), lineColor);
1092  }
1093  }
1094  }
1095  totalWidth += scaleWidth;
1096  }
1097  }
1098  }
1099 
1100  private void DrawYAxisTick(VertexHelper vh, int yAxisIndex, YAxis yAxis)
1101  {
1102  if (AxisHelper.NeedShowSplit(yAxis))
1103  {
1104  var grid = GetAxisGridOrDefault(yAxis);
1105  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
1106  var size = AxisHelper.GetScaleNumber(yAxis, grid.runtimeWidth, dataZoom);
1107  var totalWidth = grid.runtimeY;
1108  for (int i = 0; i < size; i++)
1109  {
1110  var scaleWidth = AxisHelper.GetScaleWidth(yAxis, grid.runtimeHeight, i + 1, dataZoom);
1111  if (i == 0 && (!yAxis.axisTick.showStartTick || yAxis.axisTick.alignWithLabel))
1112  {
1113  totalWidth += scaleWidth;
1114  continue;
1115  }
1116  if (i == size - 1 && !yAxis.axisTick.showEndTick)
1117  {
1118  totalWidth += scaleWidth;
1119  continue;
1120  }
1121  if (yAxis.axisTick.show)
1122  {
1123  float pX = 0;
1124  float pY = totalWidth;
1125  if (yAxis.boundaryGap && yAxis.axisTick.alignWithLabel) pY -= scaleWidth / 2;
1126  var startX = grid.runtimeX + GetYAxisOnZeroOffset(yAxis) + yAxis.offset;
1127  startX -= yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
1128  if (yAxis.IsValue() && yAxis.IsRight()) startX += grid.runtimeWidth;
1129  bool inside = yAxis.axisTick.inside;
1130  if ((inside && yAxis.IsLeft()) || (!inside && yAxis.IsRight()))
1131  {
1132  pX += startX + yAxis.axisTick.GetLength(m_Theme.axis.tickLength);
1133  }
1134  else
1135  {
1136  pX += startX - yAxis.axisTick.GetLength(m_Theme.axis.tickLength);
1137  }
1138  UGL.DrawLine(vh, new Vector3(startX, pY), new Vector3(pX, pY),
1139  yAxis.axisTick.GetWidth(m_Theme.axis.tickWidth),
1140  yAxis.axisTick.GetColor(m_Theme.axis.tickColor));
1141  }
1142  totalWidth += scaleWidth;
1143  }
1144  }
1145  if (yAxis.show && yAxis.axisLine.show && yAxis.axisLine.showArrow)
1146  {
1147  var grid = GetAxisGridOrDefault(yAxis);
1148  var lineX = grid.runtimeX + GetYAxisOnZeroOffset(yAxis);
1149  if (yAxis.IsValue() && yAxis.IsRight()) lineX += grid.runtimeWidth;
1150  var inverse = yAxis.IsValue() && yAxis.inverse;
1151  var axisArrow = yAxis.axisLine.arrow;
1152  if (inverse)
1153  {
1154  var startPos = new Vector3(lineX, grid.runtimeY + grid.runtimeHeight);
1155  var arrowPos = new Vector3(lineX, grid.runtimeY);
1156  UGL.DrawArrow(vh, startPos, arrowPos, axisArrow.width, axisArrow.height,
1157  axisArrow.offset, axisArrow.dent,
1158  axisArrow.GetColor(yAxis.axisLine.GetColor(m_Theme.axis.lineColor)));
1159  }
1160  else
1161  {
1162  var lineWidth = yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
1163  var startPos = new Vector3(lineX, grid.runtimeX);
1164  var arrowPos = new Vector3(lineX, grid.runtimeY + grid.runtimeHeight + lineWidth);
1165  UGL.DrawArrow(vh, startPos, arrowPos, axisArrow.width, axisArrow.height,
1166  axisArrow.offset, axisArrow.dent,
1167  axisArrow.GetColor(yAxis.axisLine.GetColor(m_Theme.axis.lineColor)));
1168  }
1169  }
1170  }
1171 
1172  private void DrawXAxisSplit(VertexHelper vh, int xAxisIndex, XAxis xAxis)
1173  {
1174  if (AxisHelper.NeedShowSplit(xAxis))
1175  {
1176  var grid = GetAxisGridOrDefault(xAxis);
1177  if (grid == null) return;
1178  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
1179  var size = AxisHelper.GetScaleNumber(xAxis, grid.runtimeWidth, dataZoom);
1180  var totalWidth = grid.runtimeX;
1181  var yAxis = m_YAxes[xAxisIndex];
1182  var zeroPos = new Vector3(grid.runtimeX, grid.runtimeY + yAxis.runtimeZeroYOffset);
1183  var lineColor = xAxis.splitLine.GetColor(m_Theme.axis.splitLineColor);
1184  var lineWidth = xAxis.splitLine.GetWidth(m_Theme.axis.lineWidth);
1185  var lineType = xAxis.splitLine.GetType(m_Theme.axis.splitLineType);
1186  for (int i = 0; i < size; i++)
1187  {
1188  var scaleWidth = AxisHelper.GetScaleWidth(xAxis, grid.runtimeWidth, i + 1, dataZoom);
1189  float pX = totalWidth;
1190  if (xAxis.boundaryGap && xAxis.axisTick.alignWithLabel)
1191  {
1192  pX -= scaleWidth / 2;
1193  }
1194  if (xAxis.splitArea.show && i < size - 1)
1195  {
1196  UGL.DrawQuadrilateral(vh, new Vector2(pX, grid.runtimeY),
1197  new Vector2(pX, grid.runtimeY + grid.runtimeHeight),
1198  new Vector2(pX + scaleWidth, grid.runtimeY + grid.runtimeHeight),
1199  new Vector2(pX + scaleWidth, grid.runtimeY),
1200  xAxis.splitArea.GetColor(i, m_Theme.axis));
1201  }
1202  if (xAxis.splitLine.show)
1203  {
1204  if (!yAxis.axisLine.show || !yAxis.axisLine.onZero || zeroPos.x != pX)
1205  {
1206  if (xAxis.splitLine.NeedShow(i))
1207  {
1208  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, new Vector3(pX, grid.runtimeY),
1209  new Vector3(pX, grid.runtimeY + grid.runtimeHeight), lineColor);
1210  }
1211  }
1212  }
1213  totalWidth += AxisHelper.GetScaleWidth(xAxis, grid.runtimeWidth, i + 1, dataZoom);
1214  }
1215  }
1216  }
1217 
1218  private void DrawXAxisTick(VertexHelper vh, int xAxisIndex, XAxis xAxis)
1219  {
1220  var grid = GetAxisGridOrDefault(xAxis);
1221  if (AxisHelper.NeedShowSplit(xAxis))
1222  {
1223  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
1224  var size = AxisHelper.GetScaleNumber(xAxis, grid.runtimeWidth, dataZoom);
1225  var totalWidth = grid.runtimeX;
1226  var yAxis = m_YAxes[xAxisIndex];
1227  for (int i = 0; i < size; i++)
1228  {
1229  var scaleWidth = AxisHelper.GetScaleWidth(xAxis, grid.runtimeWidth, i + 1, dataZoom);
1230  if (i == 0 && (!xAxis.axisTick.showStartTick || xAxis.axisTick.alignWithLabel))
1231  {
1232  totalWidth += scaleWidth;
1233  continue;
1234  }
1235  if (i == size - 1 && !xAxis.axisTick.showEndTick)
1236  {
1237  totalWidth += scaleWidth;
1238  continue;
1239  }
1240  if (xAxis.axisTick.show)
1241  {
1242  float pX = totalWidth;
1243  float pY = 0;
1244  if (xAxis.boundaryGap && xAxis.axisTick.alignWithLabel) pX -= scaleWidth / 2;
1245  var startY = grid.runtimeY + xAxis.offset - xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
1246  if (xAxis.IsTop()) startY += grid.runtimeHeight;
1247  else startY += GetXAxisOnZeroOffset(xAxis);
1248  bool inside = xAxis.axisTick.inside;
1249  if ((inside && xAxis.IsBottom()) || (!inside && xAxis.IsTop()))
1250  {
1251  pY += startY + xAxis.axisTick.GetLength(m_Theme.axis.tickLength);
1252  }
1253  else
1254  {
1255  pY += startY - xAxis.axisTick.GetLength(m_Theme.axis.tickLength);
1256  }
1257  UGL.DrawLine(vh, new Vector3(pX, startY), new Vector3(pX, pY),
1258  xAxis.axisTick.GetWidth(m_Theme.axis.tickWidth),
1259  xAxis.axisTick.GetColor(m_Theme.axis.tickColor));
1260  }
1261  totalWidth += scaleWidth;
1262  }
1263  }
1264  if (xAxis.show && xAxis.axisLine.show && xAxis.axisLine.showArrow)
1265  {
1266  var lineY = grid.runtimeY + xAxis.offset;
1267  if (xAxis.IsTop()) lineY += grid.runtimeHeight;
1268  else lineY += GetXAxisOnZeroOffset(xAxis);
1269  var inverse = xAxis.IsValue() && xAxis.inverse;
1270  var axisArrow = xAxis.axisLine.arrow;
1271  if (inverse)
1272  {
1273  var startPos = new Vector3(grid.runtimeX + grid.runtimeWidth, lineY);
1274  var arrowPos = new Vector3(grid.runtimeX, lineY);
1275  UGL.DrawArrow(vh, startPos, arrowPos, axisArrow.width, axisArrow.height,
1276  axisArrow.offset, axisArrow.dent,
1277  axisArrow.GetColor(xAxis.axisLine.GetColor(m_Theme.axis.lineColor)));
1278  }
1279  else
1280  {
1281  var startPos = new Vector3(grid.runtimeX, lineY);
1282  var arrowPos = new Vector3(grid.runtimeX + grid.runtimeWidth + xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth), lineY);
1283  UGL.DrawArrow(vh, startPos, arrowPos, axisArrow.width, axisArrow.height,
1284  axisArrow.offset, axisArrow.dent,
1285  axisArrow.GetColor(xAxis.axisLine.GetColor(m_Theme.axis.lineColor)));
1286  }
1287  }
1288  }
1289 
1290  private void DrawXAxisLine(VertexHelper vh, int xAxisIndex, XAxis xAxis)
1291  {
1292  if (xAxis.show && xAxis.axisLine.show)
1293  {
1294  var grid = GetAxisGridOrDefault(xAxis);
1295  var inverse = xAxis.IsValue() && xAxis.inverse;
1296  var offset = AxisHelper.GetAxisLineSymbolOffset(xAxis);
1297  var lineY = grid.runtimeY + xAxis.offset;
1298  if (xAxis.IsTop()) lineY += grid.runtimeHeight;
1299  else lineY += GetXAxisOnZeroOffset(xAxis);
1300  var lineWidth = xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
1301  var lineType = xAxis.axisLine.GetType(m_Theme.axis.lineType);
1302  var lineColor = xAxis.axisLine.GetColor(m_Theme.axis.lineColor);
1303  var left = new Vector3(grid.runtimeX - lineWidth - (inverse ? offset : 0), lineY);
1304  var right = new Vector3(grid.runtimeX + grid.runtimeWidth + lineWidth + (!inverse ? offset : 0), lineY);
1305  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, left, right, lineColor);
1306  }
1307  }
1308 
1309  private void DrawYAxisLine(VertexHelper vh, int yAxisIndex, YAxis yAxis)
1310  {
1311  if (yAxis.show && yAxis.axisLine.show)
1312  {
1313  var grid = GetAxisGridOrDefault(yAxis);
1314  var offset = AxisHelper.GetAxisLineSymbolOffset(yAxis);
1315  var inverse = yAxis.IsValue() && yAxis.inverse;
1316  var lineX = grid.runtimeX + yAxis.offset;
1317  if (yAxis.IsRight()) lineX += grid.runtimeWidth;
1318  else lineX += GetYAxisOnZeroOffset(yAxis);
1319  var lineWidth = yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
1320  var lineType = yAxis.axisLine.GetType(m_Theme.axis.lineType);
1321  var lineColor = yAxis.axisLine.GetColor(m_Theme.axis.lineColor);
1322  var bottom = new Vector3(lineX, grid.runtimeY - lineWidth - (inverse ? offset : 0));
1323  var top = new Vector3(lineX, grid.runtimeY + grid.runtimeHeight + lineWidth + (!inverse ? offset : 0));
1324  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, bottom, top, lineColor);
1325  }
1326  }
1327 
1328 
1329 
1330  protected void DrawXTooltipIndicator(VertexHelper vh)
1331  {
1332  if (!tooltip.show || !tooltip.IsSelected()) return;
1333  if (tooltip.type == Tooltip.Type.None) return;
1334  if (tooltip.runtimeGridIndex < 0) return;
1335 
1336  var grid = GetGrid(tooltip.runtimeGridIndex);
1337  if (grid == null) return;
1338  var lineType = tooltip.lineStyle.GetType(m_Theme.tooltip.lineType);
1339  var lineWidth = tooltip.lineStyle.GetWidth(m_Theme.tooltip.lineWidth);
1340  for (int i = 0; i < m_XAxes.Count; i++)
1341  {
1342  var xAxis = m_XAxes[i];
1343  if (!xAxis.show) continue;
1344  if (tooltip.runtimeXValues[i] < 0) continue;
1345  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
1346  int dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoom).Count : 0;
1347  float splitWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, dataCount, dataZoom);
1348  switch (tooltip.type)
1349  {
1350  case Tooltip.Type.Corss:
1351  case Tooltip.Type.Line:
1352  float pX = (float)(grid.runtimeX + tooltip.runtimeXValues[i] * splitWidth
1353  + (xAxis.boundaryGap ? splitWidth / 2 : 0));
1354  if (xAxis.IsValue()) pX = tooltip.runtimePointerPos.x;
1355  Vector2 sp = new Vector2(pX, grid.runtimeY);
1356  Vector2 ep = new Vector2(pX, grid.runtimeY + grid.runtimeHeight);
1357  var lineColor = TooltipHelper.GetLineColor(tooltip, m_Theme);
1358  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
1359  if (tooltip.type == Tooltip.Type.Corss)
1360  {
1361  sp = new Vector2(grid.runtimeX, tooltip.runtimePointerPos.y);
1362  ep = new Vector2(grid.runtimeX + grid.runtimeWidth, tooltip.runtimePointerPos.y);
1363  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
1364  }
1365  break;
1366  case Tooltip.Type.Shadow:
1367  float tooltipSplitWid = splitWidth < 1 ? 1 : splitWidth;
1368  pX = (float)(grid.runtimeX + splitWidth * tooltip.runtimeXValues[i] -
1369  (xAxis.boundaryGap ? 0 : splitWidth / 2));
1370  if (xAxis.IsValue()) pX = (float)tooltip.runtimeXValues[i];
1371  float pY = grid.runtimeY + grid.runtimeHeight;
1372  Vector3 p1 = new Vector3(pX, grid.runtimeY);
1373  Vector3 p2 = new Vector3(pX, pY);
1374  Vector3 p3 = new Vector3(pX + tooltipSplitWid, pY);
1375  Vector3 p4 = new Vector3(pX + tooltipSplitWid, grid.runtimeY);
1376  UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, m_Theme.tooltip.areaColor);
1377  break;
1378  }
1379  }
1380  }
1381 
1382  protected void DrawYTooltipIndicator(VertexHelper vh)
1383  {
1384  if (!tooltip.show || !tooltip.IsSelected()) return;
1385  if (tooltip.type == Tooltip.Type.None) return;
1386  if (tooltip.runtimeGridIndex < 0) return;
1387 
1388  var grid = GetGrid(tooltip.runtimeGridIndex);
1389  if (grid == null) return;
1390  var lineType = tooltip.lineStyle.GetType(m_Theme.tooltip.lineType);
1391  var lineWidth = tooltip.lineStyle.GetWidth(m_Theme.tooltip.lineWidth);
1392  for (int i = 0; i < m_YAxes.Count; i++)
1393  {
1394  var yAxis = m_YAxes[i];
1395  if (!yAxis.show) continue;
1396  if (tooltip.runtimeYValues[i] < 0) continue;
1397  var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
1398  int dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoom).Count : 0;
1399  float splitWidth = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, dataCount, dataZoom);
1400  switch (tooltip.type)
1401  {
1402  case Tooltip.Type.Corss:
1403  case Tooltip.Type.Line:
1404  float pY = (float)(grid.runtimeY + tooltip.runtimeYValues[i] * splitWidth + (yAxis.boundaryGap ? splitWidth / 2 : 0));
1405  Vector2 sp = new Vector2(grid.runtimeX, pY);
1406  Vector2 ep = new Vector2(grid.runtimeX + grid.runtimeWidth, pY);
1407  var lineColor = TooltipHelper.GetLineColor(tooltip, m_Theme);
1408  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
1409  if (tooltip.type == Tooltip.Type.Corss)
1410  {
1411  sp = new Vector2(grid.runtimeX, tooltip.runtimePointerPos.y);
1412  ep = new Vector2(grid.runtimeX + grid.runtimeWidth, tooltip.runtimePointerPos.y);
1413  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
1414  }
1415  break;
1416  case Tooltip.Type.Shadow:
1417  float tooltipSplitWid = splitWidth < 1 ? 1 : splitWidth;
1418  float pX = grid.runtimeX + grid.runtimeWidth;
1419  pY = (float)(grid.runtimeY + splitWidth * tooltip.runtimeYValues[i] -
1420  (yAxis.boundaryGap ? 0 : splitWidth / 2));
1421  Vector3 p1 = new Vector3(grid.runtimeX, pY);
1422  Vector3 p2 = new Vector3(grid.runtimeX, pY + tooltipSplitWid);
1423  Vector3 p3 = new Vector3(pX, pY + tooltipSplitWid);
1424  Vector3 p4 = new Vector3(pX, pY);
1425  UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, m_Theme.tooltip.areaColor);
1426  break;
1427  }
1428  }
1429  }
1430 
1431  private void CheckRaycastTarget()
1432  {
1433  var anyDataZoom = false;
1434  foreach (var dataZoom in dataZooms)
1435  {
1436  if (dataZoom.enable) anyDataZoom = true;
1437  }
1438  var ray = anyDataZoom
1439  || (visualMap != null && visualMap.enable && visualMap.show && visualMap.calculable);
1440  if (raycastTarget != ray)
1441  {
1442  raycastTarget = ray;
1443  }
1444  }
1445 
1446  public bool IsAnyYAxisIsCategory()
1447  {
1448  foreach (var yAxis in m_YAxes)
1449  {
1450  if (yAxis.type == Axis.AxisType.Category)
1451  {
1452  return true;
1453  }
1454  }
1455  return false;
1456  }
1457 
1458  protected virtual void DrawLabelBackground(VertexHelper vh)
1459  {
1460  var isYAxis = IsAnyYAxisIsCategory();
1461  for (int n = 0; n < m_Series.Count; n++)
1462  {
1463  var serie = m_Series.GetSerie(n);
1464  if (!serie.show) continue;
1465  if (serie.IsPerformanceMode()) continue;
1466  if (!serie.IsCoordinateSerie()) continue;
1467  DataZoomHelper.GetSerieRelatedDataZoom(serie, dataZooms, out var xDataZoom, out var yDataZoom);
1468  var showData = serie.GetDataList(xDataZoom);
1469  for (int j = 0; j < showData.Count; j++)
1470  {
1471  var serieData = showData[j];
1472  if (serieData.labelObject == null) continue;
1473  var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.highlighted);
1474  serieData.index = j;
1475  if (serieLabel.show && j < serie.dataPoints.Count)
1476  {
1477  var pos = serie.dataPoints[j];
1478 
1479  var isIngore = ChartHelper.IsIngore(pos);
1480  if (isIngore)
1481  {
1482  serieData.SetLabelActive(false);
1483  }
1484  else
1485  {
1486  Internal_RefreshLabelPosition(serie, serieData, serieLabel, pos, serie.type == SerieType.Bar, isYAxis);
1487  m_RefreshLabel = true;
1488  if (serieLabel.show) DrawLabelBackground(vh, serie, serieData);
1489  }
1490  }
1491  else
1492  {
1493  serieData.SetLabelActive(false);
1494  }
1495  }
1496  }
1497  }
1498 
1499  public void Internal_RefreshLabelPosition(Serie serie, SerieData serieData, SerieLabel serieLabel, Vector3 pos, bool IsNeedCheckPosition, bool isYAxis)
1500  {
1501  if (IsNeedCheckPosition)
1502  {
1503  var value = serieData.data[1];
1504  var zeroPos = Vector3.zero;
1505  var lastStackSerie = SeriesHelper.GetLastStackSerie(m_Series, serie.index);
1506  if (serieLabel.position == SerieLabel.Position.Bottom || serieLabel.position == SerieLabel.Position.Center)
1507  {
1508  if (isYAxis)
1509  {
1510  var xAxis = m_XAxes[serie.xAxisIndex];
1511  var grid = GetAxisGridOrDefault(xAxis);
1512  zeroPos = new Vector3(grid.runtimeX + xAxis.runtimeZeroXOffset, grid.runtimeY);
1513  }
1514  else
1515  {
1516  var yAxis = m_YAxes[serie.yAxisIndex];
1517  var grid = GetAxisGridOrDefault(yAxis);
1518  zeroPos = new Vector3(grid.runtimeX, grid.runtimeY + yAxis.runtimeZeroYOffset);
1519  }
1520  }
1521  var bottomPos = lastStackSerie == null ? zeroPos : lastStackSerie.dataPoints[serieData.index];
1522  switch (serieLabel.position)
1523  {
1524  case SerieLabel.Position.Center:
1525 
1526  pos = isYAxis ? new Vector3(bottomPos.x + (pos.x - bottomPos.x) / 2, pos.y) :
1527  new Vector3(pos.x, bottomPos.y + (pos.y - bottomPos.y) / 2);
1528  break;
1529  case SerieLabel.Position.Bottom:
1530  pos = isYAxis ? new Vector3(bottomPos.x, pos.y) : new Vector3(pos.x, bottomPos.y);
1531  break;
1532  }
1533  }
1534  serieData.labelPosition = pos;
1535  }
1536 
1537  protected override void OnRefreshLabel()
1538  {
1539  base.OnRefreshLabel();
1540  var isYAxis = IsAnyYAxisIsCategory();
1541  var anyPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
1542 
1543  for (int i = 0; i < m_Series.Count; i++)
1544  {
1545  var serie = m_Series.GetSerie(i);
1546  if (serie.IsPerformanceMode()) continue;
1547  if (!serie.IsCoordinateSerie()) continue;
1548  var total = serie.yTotal;
1549  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar);
1550  DataZoomHelper.GetSerieRelatedDataZoom(serie, dataZooms, out var xDataZoom, out var yDataZoom);
1551  var showData = serie.GetDataList(xDataZoom);
1552  if (xDataZoom != null)
1553  ChartHelper.HideAllObject(m_SerieLabelRoot, "label_" + i);
1554  for (int j = 0; j < showData.Count; j++)
1555  {
1556  var serieData = showData[j];
1557  if (serieData.labelObject == null) continue;
1558  if (j >= serie.dataPoints.Count)
1559  {
1560  serieData.SetLabelActive(false);
1561  serieData.SetIconActive(false);
1562  continue;
1563  }
1564  serieData.labelObject.SetActive(true);
1565  var pos = serie.dataPoints[j];
1566  var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
1567  var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
1568  var dimension = 1;
1569  var isIgnore = serie.IsIgnoreIndex(j);
1570  Internal_RefreshLabelPosition(serie, serieData, serieLabel, pos, serie.type == SerieType.Bar, isYAxis);
1571  serieData.labelObject.SetPosition(serieData.labelPosition);
1572  serieData.labelObject.UpdateIcon(iconStyle);
1573  if (serie.show && serieLabel.show && serieData.canShowLabel && !isIgnore)
1574  {
1575  double value = 0;
1576 
1577  if (serie.type == SerieType.Heatmap)
1578  {
1579  dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count);
1580  }
1581 
1582  SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, theme, i);
1583 
1584  value = serieData.data[dimension];
1585  var content = "";
1586  if (anyPercentStack && isPercentStack)
1587  {
1588  var tempTotal = Internal_GetBarSameStackTotalValue(serie.stack, j, SerieType.Custom);
1589  content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, tempTotal,
1590  serieLabel, theme.GetColor(i));
1591  }
1592  else
1593  {
1594  content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
1595  serieLabel, theme.GetColor(i));
1596  }
1597  serieData.SetLabelActive(serieData.labelPosition != Vector3.zero);
1598  var invert = serieLabel.autoOffset
1599  && serie.type == SerieType.Line
1600  && SerieHelper.IsDownPoint(serie, j)
1601  && !serie.areaStyle.show;
1602  serieData.labelObject.SetLabelPosition(invert ? -serieLabel.offset : serieLabel.offset);
1603  if (serieData.labelObject.SetText(content)) RefreshChart();
1604  }
1605  else
1606  {
1607  serieData.SetLabelActive(false);
1608  }
1609  }
1610  }
1611  }
1612 
1613 
1614 
1615 
1616  public void Internal_CheckClipAndDrawPolygon(VertexHelper vh, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4,
1617  Color32 color, bool clip, Grid grid)
1618  {
1619  Internal_CheckClipAndDrawPolygon(vh, p1, p2, p3, p4, color, color, clip, grid);
1620  }
1621 
1622  public void Internal_CheckClipAndDrawPolygon(VertexHelper vh, Vector3 p, float radius, Color32 color,
1623  bool clip, bool vertical, Grid grid)
1624  {
1625  if (!IsInChart(p)) return;
1626  if (!clip || (clip && (IsInGrid(grid, p))))
1627  UGL.DrawSquare(vh, p, radius, color);
1628  }
1629 
1630  public void Internal_CheckClipAndDrawPolygon(VertexHelper vh, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4,
1631  Color32 startColor, Color32 toColor, bool clip, Grid grid)
1632  {
1633  ClampInChart(ref p1);
1634  ClampInChart(ref p2);
1635  ClampInChart(ref p3);
1636  ClampInChart(ref p4);
1637  if (clip)
1638  {
1639  p1 = ClampInGrid(grid, p1);
1640  p2 = ClampInGrid(grid, p2);
1641  p3 = ClampInGrid(grid, p3);
1642  p4 = ClampInGrid(grid, p4);
1643  }
1644  if (!clip || (clip && (IsInGrid(grid, p1) && IsInGrid(grid, p2) && IsInGrid(grid, p3) && IsInGrid(grid, p4))))
1645  UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, startColor, toColor);
1646  }
1647 
1648  public void Internal_CheckClipAndDrawPolygon(VertexHelper vh, ref Vector3 p1, ref Vector3 p2, ref Vector3 p3, ref Vector3 p4,
1649  Color32 startColor, Color32 toColor, bool clip, Grid grid)
1650  {
1651  ClampInChart(ref p1);
1652  ClampInChart(ref p2);
1653  ClampInChart(ref p3);
1654  ClampInChart(ref p4);
1655  if (clip)
1656  {
1657  p1 = ClampInGrid(grid, p1);
1658  p2 = ClampInGrid(grid, p2);
1659  p3 = ClampInGrid(grid, p3);
1660  p4 = ClampInGrid(grid, p4);
1661  }
1662  if (!clip
1663  || (clip && (IsInGrid(grid, p1) && IsInGrid(grid, p2) && IsInGrid(grid, p3) && IsInGrid(grid, p4))))
1664  UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, startColor, toColor);
1665  }
1666 
1667  public void Internal_CheckClipAndDrawTriangle(VertexHelper vh, Vector3 p1, Vector3 p2, Vector3 p3, Color32 color,
1668  bool clip, Grid grid)
1669  {
1670  Internal_CheckClipAndDrawTriangle(vh, p1, p2, p3, color, color, color, clip, grid);
1671  }
1672 
1673  public void Internal_CheckClipAndDrawTriangle(VertexHelper vh, Vector3 p1, Vector3 p2, Vector3 p3, Color32 color,
1674  Color32 color2, Color32 color3, bool clip, Grid grid)
1675  {
1676  if (!IsInChart(p1) || !IsInChart(p2) || !IsInChart(p3)) return;
1677  if (!clip || (clip && (IsInGrid(grid, p1) || IsInGrid(grid, p2) || IsInGrid(grid, p3))))
1678  UGL.DrawTriangle(vh, p1, p2, p3, color, color2, color3);
1679  }
1680 
1681  public void Internal_CheckClipAndDrawLine(VertexHelper vh, Vector3 p1, Vector3 p2, float size, Color32 color,
1682  bool clip, Grid grid)
1683  {
1684  if (!IsInChart(p1) || !IsInChart(p2)) return;
1685  if (!clip || (clip && (IsInGrid(grid, p1) || IsInGrid(grid, p2))))
1686  UGL.DrawLine(vh, p1, p2, size, color);
1687  }
1688 
1689  public void Internal_CheckClipAndDrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize, float tickness,
1690  Vector3 pos, Color32 color, Color32 toColor, Color32 backgroundColor, float gap, bool clip, float[] cornerRadius,
1691  Grid grid, Vector3 startPos)
1692  {
1693  if (!IsInChart(pos)) return;
1694  if (!clip || (clip && (IsInGrid(grid, pos))))
1695  DrawSymbol(vh, type, symbolSize, tickness, pos, color, toColor, backgroundColor, gap, cornerRadius, startPos);
1696  }
1697 
1698  public void Internal_CheckClipAndDrawZebraLine(VertexHelper vh, Vector3 p1, Vector3 p2, float size, float zebraWidth,
1699  float zebraGap, Color32 color, Color32 toColor, bool clip, Grid grid)
1700  {
1701  ClampInChart(ref p1);
1702  ClampInChart(ref p2);
1703  UGL.DrawZebraLine(vh, p1, p2, size, zebraWidth, zebraGap, color, toColor);
1704  }
1705 
1706  protected Color32 GetXLerpColor(Color32 areaColor, Color32 areaToColor, Vector3 pos, Grid grid)
1707  {
1708  if (ChartHelper.IsValueEqualsColor(areaColor, areaToColor)) return areaColor;
1709  return Color32.Lerp(areaToColor, areaColor, (pos.y - grid.runtimeY) / grid.runtimeHeight);
1710  }
1711 
1712  protected Color32 GetYLerpColor(Color32 areaColor, Color32 areaToColor, Vector3 pos, Grid grid)
1713  {
1714  if (ChartHelper.IsValueEqualsColor(areaColor, areaToColor)) return areaColor;
1715  return Color32.Lerp(areaToColor, areaColor, (pos.x - grid.runtimeX) / grid.runtimeWidth);
1716  }
1717 
1718  public Grid GetAxisGridOrDefault(Axis axis)
1719  {
1720  var index = axis.gridIndex;
1721  if (index >= 0 && index < m_Grids.Count)
1722  {
1723  return m_Grids[index];
1724  }
1725  else if (m_Grids.Count > 0)
1726  {
1727  return m_Grids[0];
1728  }
1729  else
1730  {
1731  return null;
1732  }
1733  }
1734 
1735  public Grid GetDataZoomGridOrDefault(DataZoom dataZoom)
1736  {
1737  Grid grid = null;
1738  if (dataZoom.xAxisIndexs != null && dataZoom.xAxisIndexs.Count > 0)
1739  {
1740  var xAxis = GetXAxis(dataZoom.xAxisIndexs[0]);
1741  grid = GetGrid(xAxis.gridIndex);
1742  }
1743  else if (dataZoom.yAxisIndexs != null && dataZoom.yAxisIndexs.Count > 0)
1744  {
1745  var yAxis = GetYAxis(dataZoom.yAxisIndexs[0]);
1746  grid = GetGrid(yAxis.gridIndex);
1747  }
1748  if (grid == null) return m_Grids[0];
1749  else return grid;
1750  }
1751 
1752  public Grid GetSerieGridOrDefault(Serie serie)
1753  {
1754  var xAxis = GetSerieXAxisOrDefault(serie);
1755  var yAxis = GetSerieYAxisOrDefault(serie);
1756  Grid grid = GetGrid(xAxis.gridIndex);
1757  if (xAxis.gridIndex != yAxis.gridIndex)
1758  {
1759  Debug.LogErrorFormat("serie {0}:{1} xAxisIndex:{2} and yAxisIndex:{3} not in the same grid.",
1760  serie.index, serie.name, serie.xAxisIndex, serie.yAxisIndex);
1761  }
1762  if (grid == null)
1763  {
1764  grid = m_Grids[0];
1765  grid.index = 0;
1766  }
1767  else
1768  {
1769  grid.index = xAxis.gridIndex;
1770  }
1771  return grid;
1772  }
1773 
1774  public XAxis GetSerieXAxisOrDefault(Serie serie)
1775  {
1776  var axis = GetXAxis(serie.xAxisIndex);
1777  if (axis == null)
1778  {
1779  Debug.LogErrorFormat("serie {0}:{1} xAxisIndex:{2} not exist.", serie.index, serie.name, serie.xAxisIndex);
1780  axis = m_XAxes[0];
1781  }
1782  return axis;
1783  }
1784 
1785  public YAxis GetSerieYAxisOrDefault(Serie serie)
1786  {
1787  var axis = GetYAxis(serie.yAxisIndex);
1788  if (axis == null)
1789  {
1790  Debug.LogErrorFormat("serie {0}:{1} yAxisIndex:{2} not exist.", serie.index, serie.name, serie.xAxisIndex);
1791  return m_YAxes[0];
1792  }
1793  return axis;
1794  }
1795 
1796  protected void UpdateSerieGridIndex()
1797  {
1798  for (int i = 0; i < m_Series.Count; i++)
1799  {
1800  var serie = m_Series.GetSerie(i);
1801  serie.index = i;
1802  var grid = GetSerieGridOrDefault(serie);
1803  serie.runtimeGridIndex = grid.index;
1804  }
1805  }
1806 
1807  public float GetXAxisOnZeroOffset(XAxis axis)
1808  {
1809  if (!axis.axisLine.onZero) return 0;
1810  foreach (var yAxis in m_YAxes)
1811  {
1812  if (yAxis.IsValue() && yAxis.gridIndex == axis.gridIndex) return yAxis.runtimeZeroYOffset;
1813  }
1814  return 0;
1815  }
1816 
1817  public float GetYAxisOnZeroOffset(YAxis axis)
1818  {
1819  if (!axis.axisLine.onZero) return 0;
1820  foreach (var xAxis in m_XAxes)
1821  {
1822  if (xAxis.IsValue() && xAxis.gridIndex == axis.gridIndex) return xAxis.runtimeZeroXOffset;
1823  }
1824  return 0;
1825  }
1826 
1827  public YAxis GetRelatedYAxis(XAxis axis)
1828  {
1829  foreach (var yAxis in m_YAxes)
1830  {
1831  if (yAxis.gridIndex == axis.gridIndex) return yAxis;
1832  }
1833  return m_YAxes[0];
1834  }
1835 
1836  public XAxis GetRelatedXAxis(YAxis axis)
1837  {
1838  foreach (var xAxis in m_XAxes)
1839  {
1840  if (xAxis.gridIndex == axis.gridIndex) return xAxis;
1841  }
1842  return m_XAxes[0];
1843  }
1844  }
1845 }
1846 
XCharts.CoordinateChart.xAxis0
XAxis? xAxis0
X轴(下)
Definition: CoordinateChart_API.cs:40
XCharts.Axis.splitLine
AxisSplitLine splitLine
axis split line. 坐标轴分割线。
Definition: Axis.cs:341
XCharts.CoordinateChart.UpdateCoordinate
void UpdateCoordinate()
更新坐标系原点和宽高
Definition: CoordinateChart_API.cs:358
XCharts.SerieType
SerieType
the type of serie. 系列类型。
Definition: Serie.cs:19
XCharts.CoordinateChart.yAxis0
YAxis? yAxis0
Y轴(左)
Definition: CoordinateChart_API.cs:48
XCharts.Grid.backgroundColor
Color backgroundColor
Background color of grid, which is transparent by default. 网格背景色,默认透明。
Definition: XGrid.cs:84
XCharts
Definition: RewardChart.cs:14
XCharts.CoordinateChart.IsValue
bool IsValue()
reutrn true when all the show axis is Value type. 纯数值坐标轴(数值轴或对数轴)。
Definition: CoordinateChart_API.cs:222
XCharts.CoordinateChart.IsInGrid
bool IsInGrid(Grid grid, Vector2 local)
坐标是否在坐标轴内。
Definition: CoordinateChart_API.cs:254
XCharts.Grid.left
float left
Distance between grid component and the left side of the container. grid 组件离容器左侧的距离。
Definition: XGrid.cs:48
XCharts.Axis.axisLine
AxisLine axisLine
axis Line. 坐标轴轴线。 ///
Definition: Axis.cs:305
XCharts.Axis.GetData
string GetData(int index)
获得指定索引的类目数据
Definition: Axis.cs:646
XUGL
Definition: UGL.cs:12
XCharts.SerieSymbolType
SerieSymbolType
the type of symbol. 标记图形的类型。
Definition: SerieSymbol.cs:18
XCharts.Grid.show
bool show
Whether to show the grid in rectangular coordinate. 是否显示直角坐标系网格。
Definition: XGrid.cs:39
XCharts.CoordinateChart.IsCategory
bool IsCategory()
纯类目轴。
Definition: CoordinateChart_API.cs:238
XCharts.CoordinateChart.grid
Grid? grid
grid component. 网格组件。
Definition: CoordinateChart_API.cs:24