CoordinateChart.cs 87 KB

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