Bez popisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TooltipHandler.cs 31KB

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