TooltipHandler.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. using System.Collections.Generic;
  2. using System.Text;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using XUGL;
  6. namespace XCharts.Runtime
  7. {
  8. [UnityEngine.Scripting.Preserve]
  9. internal sealed class TooltipHandler : MainComponentHandler<Tooltip>
  10. {
  11. private Dictionary<string, ChartLabel> m_IndicatorLabels = new Dictionary<string, ChartLabel>();
  12. private GameObject m_LabelRoot;
  13. private ISerieContainer m_PointerContainer;
  14. public override void InitComponent()
  15. {
  16. InitTooltip(component);
  17. }
  18. public override void BeforceSerieUpdate()
  19. {
  20. UpdateTooltipData(component);
  21. }
  22. public override void Update()
  23. {
  24. UpdateTooltip(component);
  25. UpdateTooltipIndicatorLabelText(component);
  26. if (component.view != null)
  27. component.view.Update();
  28. }
  29. public override void DrawUpper(VertexHelper vh)
  30. {
  31. DrawTooltipIndicator(vh, component);
  32. }
  33. private void InitTooltip(Tooltip tooltip)
  34. {
  35. tooltip.painter = chart.m_PainterUpper;
  36. tooltip.refreshComponent = delegate ()
  37. {
  38. var objName = ChartCached.GetComponentObjectName(tooltip);
  39. tooltip.gameObject = ChartHelper.AddObject(objName, chart.transform, chart.chartMinAnchor,
  40. chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
  41. var tooltipObject = tooltip.gameObject;
  42. tooltipObject.transform.localPosition = Vector3.zero;
  43. tooltipObject.hideFlags = chart.chartHideFlags;
  44. var parent = tooltipObject.transform;
  45. ChartHelper.HideAllObject(tooltipObject.transform);
  46. tooltip.view = TooltipView.CreateView(tooltip, chart.theme, parent);
  47. tooltip.SetActive(false);
  48. m_LabelRoot = ChartHelper.AddObject("label", tooltip.gameObject.transform, chart.chartMinAnchor,
  49. chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
  50. ChartHelper.HideAllObject(m_LabelRoot);
  51. m_IndicatorLabels.Clear();
  52. foreach (var com in chart.components)
  53. {
  54. if (com is Axis)
  55. {
  56. var axis = com as Axis;
  57. var aligment = (com is AngleAxis) ? TextAnchor.MiddleCenter : axis.context.aligment;
  58. var labelName = ChartCached.GetComponentObjectName(axis);
  59. var item = ChartHelper.AddTooltipIndicatorLabel(component, labelName, m_LabelRoot.transform,
  60. chart.theme, aligment, axis.indicatorLabel);
  61. item.SetActive(false);
  62. m_IndicatorLabels[labelName] = item;
  63. }
  64. }
  65. };
  66. tooltip.refreshComponent();
  67. }
  68. private ChartLabel GetIndicatorLabel(Axis axis)
  69. {
  70. if (m_LabelRoot == null) return null;
  71. var key = ChartCached.GetComponentObjectName(axis);
  72. if (m_IndicatorLabels.ContainsKey(key))
  73. {
  74. return m_IndicatorLabels[key];
  75. }
  76. else
  77. {
  78. var item = ChartHelper.AddTooltipIndicatorLabel(component, key, m_LabelRoot.transform,
  79. chart.theme, TextAnchor.MiddleCenter, axis.indicatorLabel);
  80. m_IndicatorLabels[key] = item;
  81. return item;
  82. }
  83. }
  84. private void UpdateTooltipData(Tooltip tooltip)
  85. {
  86. showTooltip = false;
  87. if (tooltip.trigger == Tooltip.Trigger.None) return;
  88. if (chart.isPointerInChart && tooltip.show)
  89. {
  90. for (int i = chart.series.Count - 1; i >= 0; i--)
  91. {
  92. var serie = chart.series[i];
  93. if (!(serie is INeedSerieContainer))
  94. {
  95. showTooltip = true;
  96. containerSeries = null;
  97. return;
  98. }
  99. }
  100. containerSeries = ListPool<Serie>.Get();
  101. UpdatePointerContainerAndSeriesAndTooltip(tooltip, ref containerSeries);
  102. if (containerSeries.Count > 0)
  103. {
  104. showTooltip = true;
  105. }
  106. }
  107. if (!showTooltip && tooltip.IsActive())
  108. {
  109. tooltip.ClearValue();
  110. tooltip.SetActive(false);
  111. }
  112. }
  113. private bool showTooltip;
  114. private List<Serie> containerSeries;
  115. private void UpdateTooltip(Tooltip tooltip)
  116. {
  117. if (!showTooltip) return;
  118. var anyTrigger = false;
  119. for (int i = chart.series.Count - 1; i >= 0; i--)
  120. {
  121. var serie = chart.series[i];
  122. if (!(serie is INeedSerieContainer))
  123. {
  124. if (SetSerieTooltip(tooltip, serie))
  125. {
  126. anyTrigger = true;
  127. chart.RefreshTopPainter();
  128. break;
  129. }
  130. }
  131. }
  132. if (containerSeries != null)
  133. {
  134. if (!SetSerieTooltip(tooltip, containerSeries))
  135. showTooltip = false;
  136. else
  137. anyTrigger = true;
  138. ListPool<Serie>.Release(containerSeries);
  139. }
  140. if (!showTooltip || !anyTrigger)
  141. {
  142. if (tooltip.context.type == Tooltip.Type.Corss && m_PointerContainer != null && m_PointerContainer.IsPointerEnter())
  143. {
  144. tooltip.SetActive(true);
  145. tooltip.SetContentActive(false);
  146. }
  147. else
  148. {
  149. tooltip.SetActive(false);
  150. }
  151. }
  152. else
  153. {
  154. chart.RefreshUpperPainter();
  155. }
  156. }
  157. private void UpdateTooltipIndicatorLabelText(Tooltip tooltip)
  158. {
  159. if (!tooltip.show) return;
  160. if (tooltip.context.type == Tooltip.Type.None) return;
  161. if (m_PointerContainer != null)
  162. {
  163. if (tooltip.context.type == Tooltip.Type.Corss)
  164. {
  165. if (m_PointerContainer is GridCoord)
  166. {
  167. var grid = m_PointerContainer as GridCoord;
  168. ChartHelper.HideAllObject(m_LabelRoot);
  169. foreach (var component in chart.components)
  170. {
  171. if (component is XAxis || component is YAxis)
  172. {
  173. var axis = component as Axis;
  174. if (axis.gridIndex == grid.index)
  175. {
  176. var label = GetIndicatorLabel(axis);
  177. SetTooltipIndicatorLabel(tooltip, axis, label);
  178. }
  179. }
  180. }
  181. }
  182. else if (m_PointerContainer is PolarCoord)
  183. {
  184. var polar = m_PointerContainer as PolarCoord;
  185. ChartHelper.HideAllObject(m_LabelRoot);
  186. foreach (var component in chart.components)
  187. {
  188. if (component is AngleAxis || component is RadiusAxis)
  189. {
  190. var axis = component as Axis;
  191. if (axis.polarIndex == polar.index)
  192. {
  193. var label = GetIndicatorLabel(axis);
  194. SetTooltipIndicatorLabel(tooltip, axis, label);
  195. }
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. private void SetTooltipIndicatorLabel(Tooltip tooltip, Axis axis, ChartLabel label)
  203. {
  204. if (label == null) return;
  205. if (double.IsNaN(axis.context.pointerValue)) return;
  206. label.SetActive(true);
  207. label.SetTextActive(true);
  208. label.SetPosition(axis.context.pointerLabelPosition + axis.indicatorLabel.offset);
  209. if (axis.IsCategory())
  210. {
  211. var index = (int)axis.context.pointerValue;
  212. var category = axis.GetData(index);
  213. label.SetText(axis.indicatorLabel.GetFormatterContent(index, category));
  214. }
  215. else if (axis.IsTime())
  216. {
  217. label.SetText(axis.indicatorLabel.GetFormatterDateTime(0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue));
  218. }
  219. else
  220. {
  221. label.SetText(axis.indicatorLabel.GetFormatterContent(0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue, axis.IsLog()));
  222. }
  223. var textColor = axis.axisLabel.textStyle.GetColor(chart.theme.axis.textColor);
  224. if (ChartHelper.IsClearColor(axis.indicatorLabel.background.color))
  225. label.color = textColor;
  226. else
  227. label.color = axis.indicatorLabel.background.color;
  228. if (ChartHelper.IsClearColor(axis.indicatorLabel.textStyle.color))
  229. label.SetTextColor(Color.white);
  230. else
  231. label.SetTextColor(axis.indicatorLabel.textStyle.color);
  232. }
  233. private void UpdatePointerContainerAndSeriesAndTooltip(Tooltip tooltip, ref List<Serie> list)
  234. {
  235. list.Clear();
  236. m_PointerContainer = null;
  237. var updateTooltipTypeAndTrigger = false;
  238. for (int i = chart.components.Count - 1; i >= 0; i--)
  239. {
  240. var component = chart.components[i];
  241. if (component is ISerieContainer)
  242. {
  243. var container = component as ISerieContainer;
  244. if (container.IsPointerEnter())
  245. {
  246. foreach (var serie in chart.series)
  247. {
  248. if (serie is INeedSerieContainer &&
  249. (serie as INeedSerieContainer).containterInstanceId == component.instanceId &&
  250. !serie.placeHolder)
  251. {
  252. if (!updateTooltipTypeAndTrigger)
  253. {
  254. updateTooltipTypeAndTrigger = true;
  255. tooltip.context.type = tooltip.type == Tooltip.Type.Auto ?
  256. serie.context.tooltipType : tooltip.type;
  257. tooltip.context.trigger = tooltip.trigger == Tooltip.Trigger.Auto ?
  258. serie.context.tooltipTrigger : tooltip.trigger;
  259. }
  260. var isTriggerAxis = tooltip.IsTriggerAxis();
  261. if (container is GridCoord)
  262. {
  263. var xAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
  264. var yAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
  265. UpdateAxisPointerDataIndex(serie, xAxis, yAxis, container as GridCoord, isTriggerAxis);
  266. }
  267. else if (container is PolarCoord)
  268. {
  269. var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, container.index);
  270. tooltip.context.angle = (float)m_AngleAxis.context.pointerValue;
  271. }
  272. list.Add(serie);
  273. if (!isTriggerAxis)
  274. chart.RefreshTopPainter();
  275. }
  276. }
  277. m_PointerContainer = container;
  278. }
  279. }
  280. }
  281. }
  282. private void UpdateAxisPointerDataIndex(Serie serie, XAxis xAxis, YAxis yAxis, GridCoord grid, bool isTriggerAxis)
  283. {
  284. serie.context.pointerAxisDataIndexs.Clear();
  285. if (xAxis == null || yAxis == null) return;
  286. if (serie is Heatmap)
  287. {
  288. GetSerieDataByXYAxis(serie, xAxis, yAxis);
  289. }
  290. else if (yAxis.IsCategory() && !xAxis.IsCategory())
  291. {
  292. if (isTriggerAxis)
  293. {
  294. var index = serie.context.dataZoomStartIndex + (int)yAxis.context.pointerValue;
  295. serie.context.pointerEnter = true;
  296. serie.context.pointerAxisDataIndexs.Add(index);
  297. serie.context.pointerItemDataIndex = index;
  298. yAxis.context.axisTooltipValue = yAxis.context.pointerValue;
  299. }
  300. }
  301. else if (yAxis.IsTime())
  302. {
  303. serie.context.pointerEnter = true;
  304. if (isTriggerAxis)
  305. GetSerieDataIndexByAxis(serie, yAxis, grid);
  306. else
  307. GetSerieDataIndexByItem(serie, yAxis, grid);
  308. }
  309. else if (xAxis.IsCategory())
  310. {
  311. if (isTriggerAxis)
  312. {
  313. var index = serie.context.dataZoomStartIndex + (int)xAxis.context.pointerValue;
  314. serie.context.pointerEnter = true;
  315. serie.context.pointerAxisDataIndexs.Add(index);
  316. serie.context.pointerItemDataIndex = index;
  317. xAxis.context.axisTooltipValue = xAxis.context.pointerValue;
  318. }
  319. }
  320. else
  321. {
  322. serie.context.pointerEnter = true;
  323. if (isTriggerAxis)
  324. GetSerieDataIndexByAxis(serie, xAxis, grid);
  325. else
  326. GetSerieDataIndexByItem(serie, xAxis, grid);
  327. }
  328. }
  329. private void GetSerieDataByXYAxis(Serie serie, Axis xAxis, Axis yAxis)
  330. {
  331. var xAxisIndex = AxisHelper.GetAxisValueSplitIndex(xAxis, xAxis.context.pointerValue, false);
  332. var yAxisIndex = AxisHelper.GetAxisValueSplitIndex(yAxis, yAxis.context.pointerValue, false);
  333. serie.context.pointerItemDataIndex = -1;
  334. if (serie is Heatmap)
  335. {
  336. var heatmap = serie as Heatmap;
  337. if (heatmap.heatmapType == HeatmapType.Count)
  338. {
  339. serie.context.pointerItemDataIndex = HeatmapHandler.GetGridKey(xAxisIndex, yAxisIndex);
  340. return;
  341. }
  342. }
  343. foreach (var serieData in serie.data)
  344. {
  345. var x = AxisHelper.GetAxisValueSplitIndex(xAxis, serieData.GetData(0), true);
  346. var y = AxisHelper.GetAxisValueSplitIndex(yAxis, serieData.GetData(1), true);
  347. if (xAxisIndex == x && y == yAxisIndex)
  348. {
  349. serie.context.pointerItemDataIndex = serieData.index;
  350. break;
  351. }
  352. }
  353. }
  354. private void GetSerieDataIndexByAxis(Serie serie, Axis axis, GridCoord grid, int dimension = 0)
  355. {
  356. var currValue = 0d;
  357. var lastValue = 0d;
  358. var nextValue = 0d;
  359. var axisValue = axis.context.pointerValue;
  360. var isTimeAxis = axis.IsTime();
  361. var dataCount = serie.dataCount;
  362. var themeSymbolSize = chart.theme.serie.scatterSymbolSize;
  363. var data = serie.data;
  364. if (!isTimeAxis)
  365. {
  366. serie.context.sortedData.Clear();
  367. for (int i = 0; i < dataCount; i++)
  368. {
  369. var serieData = serie.data[i];
  370. serie.context.sortedData.Add(serieData);
  371. }
  372. serie.context.sortedData.Sort(delegate (SerieData a, SerieData b)
  373. {
  374. return a.GetData(dimension).CompareTo(b.GetData(dimension));
  375. });
  376. data = serie.context.sortedData;
  377. }
  378. serie.context.pointerAxisDataIndexs.Clear();
  379. for (int i = 0; i < dataCount; i++)
  380. {
  381. var serieData = data[i];
  382. currValue = serieData.GetData(dimension);
  383. if (i == 0 && i + 1 < dataCount)
  384. {
  385. nextValue = data[i + 1].GetData(dimension);
  386. if (axisValue <= currValue + (nextValue - currValue) / 2)
  387. {
  388. serie.context.pointerAxisDataIndexs.Add(serieData.index);
  389. break;
  390. }
  391. }
  392. else if (i == dataCount - 1)
  393. {
  394. if (axisValue > lastValue + (currValue - lastValue) / 2)
  395. {
  396. serie.context.pointerAxisDataIndexs.Add(serieData.index);
  397. break;
  398. }
  399. }
  400. else if (i + 1 < dataCount)
  401. {
  402. nextValue = data[i + 1].GetData(dimension);
  403. if (axisValue > (currValue - (currValue - lastValue) / 2) && axisValue <= currValue + (nextValue - currValue) / 2)
  404. {
  405. serie.context.pointerAxisDataIndexs.Add(serieData.index);
  406. break;
  407. }
  408. }
  409. lastValue = currValue;
  410. }
  411. if (serie.context.pointerAxisDataIndexs.Count > 0)
  412. {
  413. var index = serie.context.pointerAxisDataIndexs[0];
  414. serie.context.pointerItemDataIndex = index;
  415. axis.context.axisTooltipValue = serie.GetSerieData(index).GetData(dimension);
  416. }
  417. else
  418. {
  419. serie.context.pointerItemDataIndex = -1;
  420. axis.context.axisTooltipValue = 0;
  421. }
  422. }
  423. private void GetSerieDataIndexByItem(Serie serie, Axis axis, GridCoord grid, int dimension = 0)
  424. {
  425. if (serie.context.pointerItemDataIndex >= 0)
  426. {
  427. axis.context.axisTooltipValue = serie.GetSerieData(serie.context.pointerItemDataIndex).GetData(dimension);
  428. }
  429. else if (component.type == Tooltip.Type.Corss)
  430. {
  431. axis.context.axisTooltipValue = axis.context.pointerValue;
  432. }
  433. else
  434. {
  435. axis.context.axisTooltipValue = 0;
  436. }
  437. }
  438. private bool SetSerieTooltip(Tooltip tooltip, Serie serie)
  439. {
  440. if (serie.context.pointerItemDataIndex < 0) return false;
  441. tooltip.context.type = tooltip.type == Tooltip.Type.Auto ? serie.context.tooltipType : tooltip.type;
  442. tooltip.context.trigger = tooltip.trigger == Tooltip.Trigger.Auto ? serie.context.tooltipTrigger : tooltip.trigger;
  443. if (tooltip.context.trigger == Tooltip.Trigger.None) return false;
  444. tooltip.context.data.param.Clear();
  445. tooltip.context.data.title = serie.serieName;
  446. tooltip.context.pointer = chart.pointerPos;
  447. serie.handler.UpdateTooltipSerieParams(serie.context.pointerItemDataIndex, false, null,
  448. tooltip.marker, tooltip.itemFormatter, tooltip.numericFormatter, tooltip.ignoreDataDefaultContent,
  449. ref tooltip.context.data.param,
  450. ref tooltip.context.data.title);
  451. TooltipHelper.ResetTooltipParamsByItemFormatter(tooltip, chart);
  452. tooltip.SetActive(true);
  453. tooltip.view.Refresh();
  454. TooltipHelper.LimitInRect(tooltip, chart.chartRect);
  455. return true;
  456. }
  457. private bool SetSerieTooltip(Tooltip tooltip, List<Serie> series)
  458. {
  459. if (tooltip.context.trigger == Tooltip.Trigger.None)
  460. return false;
  461. if (series.Count <= 0)
  462. return false;
  463. string category = null;
  464. var showCategory = false;
  465. var isTriggerByAxis = false;
  466. var isTriggerByItem = false;
  467. var dataIndex = -1;
  468. tooltip.context.data.param.Clear();
  469. tooltip.context.pointer = chart.pointerPos;
  470. if (m_PointerContainer is GridCoord)
  471. {
  472. GetAxisCategory(m_PointerContainer.index, ref dataIndex, ref category);
  473. if (tooltip.context.trigger == Tooltip.Trigger.Axis)
  474. {
  475. isTriggerByAxis = true;
  476. if (series.Count <= 1)
  477. {
  478. showCategory = true;
  479. tooltip.context.data.title = series[0].serieName;
  480. }
  481. else
  482. tooltip.context.data.title = category;
  483. }
  484. else if (tooltip.context.trigger == Tooltip.Trigger.Item)
  485. {
  486. isTriggerByItem = true;
  487. showCategory = series.Count <= 1;
  488. }
  489. }
  490. for (int i = 0; i < series.Count; i++)
  491. {
  492. var serie = series[i];
  493. if (!serie.show) continue;
  494. if (isTriggerByItem && serie.context.pointerItemDataIndex < 0) continue;
  495. serie.context.isTriggerByAxis = isTriggerByAxis;
  496. if (isTriggerByAxis && dataIndex >= 0 && serie.context.pointerItemDataIndex < 0)
  497. serie.context.pointerItemDataIndex = dataIndex;
  498. serie.handler.UpdateTooltipSerieParams(dataIndex, showCategory, category,
  499. tooltip.marker, tooltip.itemFormatter, tooltip.numericFormatter,
  500. tooltip.ignoreDataDefaultContent,
  501. ref tooltip.context.data.param,
  502. ref tooltip.context.data.title);
  503. }
  504. TooltipHelper.ResetTooltipParamsByItemFormatter(tooltip, chart);
  505. if (tooltip.context.data.param.Count > 0 || !string.IsNullOrEmpty(tooltip.context.data.title))
  506. {
  507. tooltip.SetActive(true);
  508. if (tooltip.view != null)
  509. tooltip.view.Refresh();
  510. TooltipHelper.LimitInRect(tooltip, chart.chartRect);
  511. return true;
  512. }
  513. return false;
  514. }
  515. private bool GetAxisCategory(int gridIndex, ref int dataIndex, ref string category)
  516. {
  517. foreach (var component in chart.components)
  518. {
  519. if (component is Axis)
  520. {
  521. var axis = component as Axis;
  522. if (axis.gridIndex == gridIndex && axis.IsCategory())
  523. {
  524. dataIndex = double.IsNaN(axis.context.pointerValue)
  525. ? axis.context.dataZoomStartIndex
  526. : axis.context.dataZoomStartIndex + (int)axis.context.pointerValue;
  527. category = axis.GetData(dataIndex);
  528. return true;
  529. }
  530. }
  531. }
  532. return false;
  533. }
  534. private void DrawTooltipIndicator(VertexHelper vh, Tooltip tooltip)
  535. {
  536. if (!tooltip.show) return;
  537. if (tooltip.context.type == Tooltip.Type.None) return;
  538. if (!IsAnySerieNeedTooltip()) return;
  539. if (m_PointerContainer is GridCoord)
  540. {
  541. var grid = m_PointerContainer as GridCoord;
  542. if (!grid.context.isPointerEnter) return;
  543. if (IsYCategoryOfGrid(grid.index))
  544. DrawYAxisIndicator(vh, tooltip, grid);
  545. else
  546. DrawXAxisIndicator(vh, tooltip, grid);
  547. }
  548. else if (m_PointerContainer is PolarCoord)
  549. {
  550. DrawPolarIndicator(vh, tooltip, m_PointerContainer as PolarCoord);
  551. }
  552. }
  553. private bool IsYCategoryOfGrid(int gridIndex)
  554. {
  555. foreach (var component in chart.GetChartComponents<YAxis>())
  556. {
  557. var yAxis = component as YAxis;
  558. if (yAxis.gridIndex == gridIndex && !yAxis.IsCategory()) return false;
  559. }
  560. foreach (var component in chart.GetChartComponents<XAxis>())
  561. {
  562. var xAxis = component as XAxis;
  563. if (xAxis.gridIndex == gridIndex && xAxis.IsCategory()) return false;
  564. }
  565. return true;
  566. }
  567. private void DrawXAxisIndicator(VertexHelper vh, Tooltip tooltip, GridCoord grid)
  568. {
  569. var xAxes = chart.GetChartComponents<XAxis>();
  570. var lineType = tooltip.lineStyle.GetType(chart.theme.tooltip.lineType);
  571. var lineWidth = tooltip.lineStyle.GetWidth(chart.theme.tooltip.lineWidth);
  572. foreach (var component in xAxes)
  573. {
  574. var xAxis = component as XAxis;
  575. if (xAxis.gridIndex == grid.index)
  576. {
  577. if (double.IsInfinity(xAxis.context.pointerValue))
  578. continue;
  579. var dataZoom = chart.GetDataZoomOfAxis(xAxis);
  580. int dataCount = chart.series.Count > 0 ? chart.series[0].GetDataList(dataZoom).Count : 0;
  581. float splitWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, dataCount, dataZoom);
  582. switch (tooltip.context.type)
  583. {
  584. case Tooltip.Type.Corss:
  585. case Tooltip.Type.Line:
  586. float pX = grid.context.x;
  587. pX += xAxis.IsCategory() ?
  588. (float)(xAxis.context.pointerValue * splitWidth + (xAxis.boundaryGap ? splitWidth / 2 : 0)) :
  589. xAxis.GetDistance(xAxis.context.axisTooltipValue, grid.context.width);
  590. if (pX < grid.context.x)
  591. break;
  592. Vector2 sp = new Vector2(pX, grid.context.y);
  593. Vector2 ep = new Vector2(pX, grid.context.y + grid.context.height);
  594. var lineColor = TooltipHelper.GetLineColor(tooltip, chart.theme.tooltip.lineColor);
  595. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
  596. if (tooltip.context.type == Tooltip.Type.Corss)
  597. {
  598. sp = new Vector2(grid.context.x, chart.pointerPos.y);
  599. ep = new Vector2(grid.context.x + grid.context.width, chart.pointerPos.y);
  600. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
  601. }
  602. break;
  603. case Tooltip.Type.Shadow:
  604. if (xAxis.IsCategory() && !double.IsInfinity(xAxis.context.pointerValue))
  605. {
  606. float tooltipSplitWid = splitWidth < 1 ? 1 : splitWidth;
  607. pX = (float)(grid.context.x + splitWidth * xAxis.context.pointerValue -
  608. (xAxis.boundaryGap ? 0 : splitWidth / 2));
  609. if (pX < grid.context.x)
  610. break;
  611. float pY = grid.context.y + grid.context.height;
  612. Vector3 p1 = chart.ClampInGrid(grid, new Vector3(pX, grid.context.y));
  613. Vector3 p2 = chart.ClampInGrid(grid, new Vector3(pX, pY));
  614. Vector3 p3 = chart.ClampInGrid(grid, new Vector3(pX + tooltipSplitWid, pY));
  615. Vector3 p4 = chart.ClampInGrid(grid, new Vector3(pX + tooltipSplitWid, grid.context.y));
  616. var areaColor = TooltipHelper.GetLineColor(tooltip, chart.theme.tooltip.areaColor);
  617. UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, areaColor);
  618. }
  619. break;
  620. }
  621. }
  622. }
  623. }
  624. private bool IsAnySerieNeedTooltip()
  625. {
  626. foreach (var serie in chart.series)
  627. {
  628. if (serie.context.pointerEnter) return true;
  629. }
  630. return false;
  631. }
  632. private void DrawYAxisIndicator(VertexHelper vh, Tooltip tooltip, GridCoord grid)
  633. {
  634. var yAxes = chart.GetChartComponents<YAxis>();
  635. var lineType = tooltip.lineStyle.GetType(chart.theme.tooltip.lineType);
  636. var lineWidth = tooltip.lineStyle.GetWidth(chart.theme.tooltip.lineWidth);
  637. foreach (var component in yAxes)
  638. {
  639. var yAxis = component as YAxis;
  640. if (yAxis.gridIndex == grid.index)
  641. {
  642. if (double.IsInfinity(yAxis.context.pointerValue))
  643. continue;
  644. var dataZoom = chart.GetDataZoomOfAxis(yAxis);
  645. int dataCount = chart.series.Count > 0 ? chart.series[0].GetDataList(dataZoom).Count : 0;
  646. float splitWidth = AxisHelper.GetDataWidth(yAxis, grid.context.height, dataCount, dataZoom);
  647. switch (tooltip.context.type)
  648. {
  649. case Tooltip.Type.Corss:
  650. case Tooltip.Type.Line:
  651. float pY = (float)(grid.context.y + yAxis.context.pointerValue * splitWidth +
  652. (yAxis.boundaryGap ? splitWidth / 2 : 0));
  653. if (pY < grid.context.y)
  654. break;
  655. Vector2 sp = new Vector2(grid.context.x, pY);
  656. Vector2 ep = new Vector2(grid.context.x + grid.context.width, pY);
  657. var lineColor = TooltipHelper.GetLineColor(tooltip, chart.theme.tooltip.lineColor);
  658. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
  659. if (tooltip.context.type == Tooltip.Type.Corss)
  660. {
  661. sp = new Vector2(chart.pointerPos.x, grid.context.y);
  662. ep = new Vector2(chart.pointerPos.x, grid.context.y + grid.context.height);
  663. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
  664. }
  665. break;
  666. case Tooltip.Type.Shadow:
  667. if (yAxis.IsCategory())
  668. {
  669. float tooltipSplitWid = splitWidth < 1 ? 1 : splitWidth;
  670. float pX = grid.context.x + grid.context.width;
  671. pY = (float)(grid.context.y + splitWidth * yAxis.context.pointerValue -
  672. (yAxis.boundaryGap ? 0 : splitWidth / 2));
  673. if (pY < grid.context.y)
  674. break;
  675. Vector3 p1 = new Vector3(grid.context.x, pY);
  676. Vector3 p2 = new Vector3(grid.context.x, pY + tooltipSplitWid);
  677. Vector3 p3 = new Vector3(pX, pY + tooltipSplitWid);
  678. Vector3 p4 = new Vector3(pX, pY);
  679. UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, chart.theme.tooltip.areaColor);
  680. }
  681. break;
  682. }
  683. }
  684. }
  685. }
  686. private void DrawPolarIndicator(VertexHelper vh, Tooltip tooltip, PolarCoord m_Polar)
  687. {
  688. if (tooltip.context.angle < 0) return;
  689. var theme = chart.theme;
  690. var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, m_Polar.index);
  691. var lineColor = TooltipHelper.GetLineColor(tooltip, theme.tooltip.lineColor);
  692. var lineType = tooltip.lineStyle.GetType(theme.tooltip.lineType);
  693. var lineWidth = tooltip.lineStyle.GetWidth(theme.tooltip.lineWidth);
  694. var cenPos = m_Polar.context.center;
  695. var radius = m_Polar.context.outsideRadius;
  696. var tooltipAngle = m_AngleAxis.GetValueAngle(tooltip.context.angle);
  697. var sp = ChartHelper.GetPos(m_Polar.context.center, m_Polar.context.insideRadius, tooltipAngle, true);
  698. var ep = ChartHelper.GetPos(m_Polar.context.center, m_Polar.context.outsideRadius, tooltipAngle, true);
  699. switch (tooltip.context.type)
  700. {
  701. case Tooltip.Type.Corss:
  702. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
  703. var dist = Vector2.Distance(chart.pointerPos, cenPos);
  704. if (dist > radius) dist = radius;
  705. var outsideRaidus = dist + tooltip.lineStyle.GetWidth(theme.tooltip.lineWidth) * 2;
  706. UGL.DrawDoughnut(vh, cenPos, dist, outsideRaidus, lineColor, Color.clear);
  707. break;
  708. case Tooltip.Type.Line:
  709. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
  710. break;
  711. case Tooltip.Type.Shadow:
  712. UGL.DrawSector(vh, cenPos, radius, lineColor, tooltipAngle - 2, tooltipAngle + 2, chart.settings.cicleSmoothness);
  713. break;
  714. }
  715. }
  716. }
  717. }