No Description
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.

MarkLineHandler.cs 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. namespace XCharts.Runtime
  5. {
  6. [UnityEngine.Scripting.Preserve]
  7. internal sealed class MarkLineHandler : MainComponentHandler<MarkLine>
  8. {
  9. private GameObject m_MarkLineLabelRoot;
  10. private bool m_RefreshLabel = false;
  11. public override void InitComponent()
  12. {
  13. m_MarkLineLabelRoot = ChartHelper.AddObject("markline", chart.transform, chart.chartMinAnchor,
  14. chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
  15. m_MarkLineLabelRoot.hideFlags = chart.chartHideFlags;
  16. ChartHelper.HideAllObject(m_MarkLineLabelRoot);
  17. InitMarkLine(component);
  18. }
  19. public override void DrawUpper(VertexHelper vh)
  20. {
  21. DrawMarkLine(vh, component);
  22. }
  23. public override void Update()
  24. {
  25. if (m_RefreshLabel)
  26. {
  27. m_RefreshLabel = false;
  28. var serie = chart.GetSerie(component.serieIndex);
  29. if (!serie.show || !component.show) return;
  30. foreach (var data in component.data)
  31. {
  32. if (data.runtimeLabel != null)
  33. {
  34. var pos = MarkLineHelper.GetLabelPosition(data);
  35. data.runtimeLabel.SetActive(data.label.show && pos != Vector3.zero);
  36. data.runtimeLabel.SetPosition(pos);
  37. data.runtimeLabel.SetText(MarkLineHelper.GetFormatterContent(serie, data));
  38. }
  39. }
  40. }
  41. }
  42. private void InitMarkLine(MarkLine markLine)
  43. {
  44. var serie = chart.GetSerie(markLine.serieIndex);
  45. if (!serie.show || !markLine.show) return;
  46. ResetTempMarkLineGroupData(markLine);
  47. var serieColor = (Color) chart.GetItemColor(serie);
  48. if (m_TempGroupData.Count > 0)
  49. {
  50. foreach (var kv in m_TempGroupData)
  51. {
  52. if (kv.Value.Count >= 2)
  53. {
  54. var data = kv.Value[0];
  55. InitMarkLineLabel(serie, data, serieColor);
  56. }
  57. }
  58. }
  59. foreach (var data in markLine.data)
  60. {
  61. if (data.group != 0) continue;
  62. InitMarkLineLabel(serie, data, serieColor);
  63. }
  64. }
  65. private void InitMarkLineLabel(Serie serie, MarkLineData data, Color serieColor)
  66. {
  67. data.painter = chart.m_PainterUpper;
  68. data.refreshComponent = delegate()
  69. {
  70. var textName = string.Format("markLine_{0}_{1}", serie.index, data.index);
  71. var content = MarkLineHelper.GetFormatterContent(serie, data);
  72. var label = ChartHelper.AddChartLabel(textName, m_MarkLineLabelRoot.transform, data.label, chart.theme.axis,
  73. content, Color.clear, TextAnchor.MiddleCenter);
  74. var pos = MarkLineHelper.GetLabelPosition(data);
  75. label.SetIconActive(false);
  76. label.SetActive(data.label.show && pos != Vector3.zero);
  77. label.SetPosition(pos);
  78. data.runtimeLabel = label;
  79. };
  80. data.refreshComponent();
  81. }
  82. private Dictionary<int, List<MarkLineData>> m_TempGroupData = new Dictionary<int, List<MarkLineData>>();
  83. private void DrawMarkLine(VertexHelper vh, MarkLine markLine)
  84. {
  85. var serie = chart.GetSerie(markLine.serieIndex);
  86. if (!serie.show || !markLine.show) return;
  87. if (markLine.data.Count == 0) return;
  88. var yAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
  89. var xAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
  90. var grid = chart.GetChartComponent<GridCoord>(xAxis.gridIndex);
  91. var dataZoom = chart.GetDataZoomOfAxis(xAxis);
  92. var animation = markLine.animation;
  93. var showData = serie.GetDataList(dataZoom);
  94. var sp = Vector3.zero;
  95. var ep = Vector3.zero;
  96. var colorIndex = chart.GetLegendRealShowNameIndex(serie.serieName);
  97. var serieColor = SerieHelper.GetLineColor(serie, null, chart.theme, colorIndex, SerieState.Normal);
  98. animation.InitProgress(0, 1f);
  99. ResetTempMarkLineGroupData(markLine);
  100. if (m_TempGroupData.Count > 0)
  101. {
  102. foreach (var kv in m_TempGroupData)
  103. {
  104. if (kv.Value.Count >= 2)
  105. {
  106. sp = GetSinglePos(xAxis, yAxis, grid, serie, dataZoom, kv.Value[0], showData.Count);
  107. ep = GetSinglePos(xAxis, yAxis, grid, serie, dataZoom, kv.Value[1], showData.Count);
  108. kv.Value[0].runtimeStartPosition = sp;
  109. kv.Value[1].runtimeEndPosition = ep;
  110. DrawMakLineData(vh, kv.Value[0], animation, serie, grid, serieColor, sp, ep);
  111. }
  112. }
  113. }
  114. foreach (var data in markLine.data)
  115. {
  116. if (data.group != 0) continue;
  117. switch (data.type)
  118. {
  119. case MarkLineType.Min:
  120. data.runtimeValue = SerieHelper.GetMinData(serie, data.dimension, dataZoom);
  121. GetStartEndPos(xAxis, yAxis, grid, data.runtimeValue, ref sp, ref ep);
  122. break;
  123. case MarkLineType.Max:
  124. data.runtimeValue = SerieHelper.GetMaxData(serie, data.dimension, dataZoom);
  125. GetStartEndPos(xAxis, yAxis, grid, data.runtimeValue, ref sp, ref ep);
  126. break;
  127. case MarkLineType.Average:
  128. data.runtimeValue = SerieHelper.GetAverageData(serie, data.dimension, dataZoom);
  129. GetStartEndPos(xAxis, yAxis, grid, data.runtimeValue, ref sp, ref ep);
  130. break;
  131. case MarkLineType.Median:
  132. data.runtimeValue = SerieHelper.GetMedianData(serie, data.dimension, dataZoom);
  133. GetStartEndPos(xAxis, yAxis, grid, data.runtimeValue, ref sp, ref ep);
  134. break;
  135. case MarkLineType.None:
  136. if (data.xPosition != 0)
  137. {
  138. data.runtimeValue = data.xPosition;
  139. var pX = grid.context.x + data.xPosition;
  140. sp = new Vector3(pX, grid.context.y);
  141. ep = new Vector3(pX, grid.context.y + grid.context.height);
  142. }
  143. else if (data.yPosition != 0)
  144. {
  145. data.runtimeValue = data.yPosition;
  146. var pY = grid.context.y + data.yPosition;
  147. sp = new Vector3(grid.context.x, pY);
  148. ep = new Vector3(grid.context.x + grid.context.width, pY);
  149. }
  150. else if (data.yValue != 0)
  151. {
  152. data.runtimeValue = data.yValue;
  153. if (yAxis.IsCategory())
  154. {
  155. var pY = AxisHelper.GetAxisPosition(grid, yAxis, data.yValue, showData.Count, dataZoom);
  156. sp = new Vector3(grid.context.x, pY);
  157. ep = new Vector3(grid.context.x + grid.context.width, pY);
  158. }
  159. else
  160. {
  161. GetStartEndPos(xAxis, yAxis, grid, data.yValue, ref sp, ref ep);
  162. }
  163. }
  164. else
  165. {
  166. data.runtimeValue = data.xValue;
  167. if (xAxis.IsCategory())
  168. {
  169. var pX = AxisHelper.GetAxisPosition(grid, xAxis, data.xValue, showData.Count, dataZoom);
  170. sp = new Vector3(pX, grid.context.y);
  171. ep = new Vector3(pX, grid.context.y + grid.context.height);
  172. }
  173. else
  174. {
  175. GetStartEndPos(xAxis, yAxis, grid, data.xValue, ref sp, ref ep);
  176. }
  177. }
  178. break;
  179. default:
  180. break;
  181. }
  182. data.runtimeStartPosition = sp;
  183. data.runtimeEndPosition = ep;
  184. DrawMakLineData(vh, data, animation, serie, grid, serieColor, sp, ep);
  185. }
  186. if (!animation.IsFinish())
  187. {
  188. animation.CheckProgress(1f);
  189. chart.RefreshTopPainter();
  190. }
  191. }
  192. private void ResetTempMarkLineGroupData(MarkLine markLine)
  193. {
  194. m_TempGroupData.Clear();
  195. for (int i = 0; i < markLine.data.Count; i++)
  196. {
  197. var data = markLine.data[i];
  198. data.index = i;
  199. if (data.group == 0) continue;
  200. if (!m_TempGroupData.ContainsKey(data.group))
  201. {
  202. m_TempGroupData[data.group] = new List<MarkLineData>();
  203. }
  204. m_TempGroupData[data.group].Add(data);
  205. }
  206. }
  207. private void DrawMakLineData(VertexHelper vh, MarkLineData data, AnimationStyle animation, Serie serie,
  208. GridCoord grid, Color32 serieColor, Vector3 sp, Vector3 ep)
  209. {
  210. if (!animation.IsFinish())
  211. ep = Vector3.Lerp(sp, ep, animation.GetCurrDetail());
  212. data.runtimeCurrentEndPosition = ep;
  213. if (sp != Vector3.zero || ep != Vector3.zero)
  214. {
  215. m_RefreshLabel = true;
  216. chart.ClampInChart(ref sp);
  217. chart.ClampInChart(ref ep);
  218. var theme = chart.theme.axis;
  219. var lineColor = ChartHelper.IsClearColor(data.lineStyle.color) ? serieColor : data.lineStyle.color;
  220. var lineWidth = data.lineStyle.width == 0 ? theme.lineWidth : data.lineStyle.width;
  221. ChartDrawer.DrawLineStyle(vh, data.lineStyle, sp, ep, lineWidth, LineStyle.Type.Dashed, lineColor, lineColor);
  222. if (data.startSymbol != null && data.startSymbol.show)
  223. {
  224. DrawMarkLineSymbol(vh, data.startSymbol, serie, grid, chart.theme, sp, sp, lineColor);
  225. }
  226. if (data.endSymbol != null && data.endSymbol.show)
  227. {
  228. DrawMarkLineSymbol(vh, data.endSymbol, serie, grid, chart.theme, ep, sp, lineColor);
  229. }
  230. }
  231. }
  232. private void DrawMarkLineSymbol(VertexHelper vh, SymbolStyle symbol, Serie serie, GridCoord grid, ThemeStyle theme,
  233. Vector3 pos, Vector3 startPos, Color32 lineColor)
  234. {
  235. float tickness = 0f;
  236. float[] cornerRadius = null;
  237. Color32 borderColor;
  238. SerieHelper.GetSymbolInfo(out borderColor, out tickness, out cornerRadius, serie, null, chart.theme);
  239. chart.DrawClipSymbol(vh, symbol.type, symbol.size, tickness, pos, lineColor, lineColor,
  240. ColorUtil.clearColor32, borderColor, symbol.gap, true, cornerRadius, grid, startPos);
  241. }
  242. private void GetStartEndPos(Axis xAxis, Axis yAxis, GridCoord grid, double value, ref Vector3 sp, ref Vector3 ep)
  243. {
  244. if (xAxis.IsCategory())
  245. {
  246. var pY = AxisHelper.GetAxisPosition(grid, yAxis, value);
  247. sp = new Vector3(grid.context.x, pY);
  248. ep = new Vector3(grid.context.x + grid.context.width, pY);
  249. }
  250. else
  251. {
  252. var pX = AxisHelper.GetAxisPosition(grid, xAxis, value);
  253. sp = new Vector3(pX, grid.context.y);
  254. ep = new Vector3(pX, grid.context.y + grid.context.height);
  255. }
  256. }
  257. private float GetAxisPosition(GridCoord grid, Axis axis, DataZoom dataZoom, int dataCount, double value)
  258. {
  259. return AxisHelper.GetAxisPosition(grid, axis, value, dataCount, dataZoom);
  260. }
  261. private Vector3 GetSinglePos(Axis xAxis, Axis yAxis, GridCoord grid, Serie serie, DataZoom dataZoom, MarkLineData data,
  262. int serieDataCount)
  263. {
  264. switch (data.type)
  265. {
  266. case MarkLineType.Min:
  267. var serieData = SerieHelper.GetMinSerieData(serie, data.dimension, dataZoom);
  268. data.runtimeValue = serieData.GetData(data.dimension);
  269. var pX = GetAxisPosition(grid, xAxis, dataZoom, serieDataCount, serieData.index);
  270. var pY = GetAxisPosition(grid, yAxis, dataZoom, serieDataCount, data.runtimeValue);
  271. return new Vector3(pX, pY);
  272. case MarkLineType.Max:
  273. serieData = SerieHelper.GetMaxSerieData(serie, data.dimension, dataZoom);
  274. data.runtimeValue = serieData.GetData(data.dimension);
  275. pX = GetAxisPosition(grid, xAxis, dataZoom, serieDataCount, serieData.index);
  276. pY = GetAxisPosition(grid, yAxis, dataZoom, serieDataCount, data.runtimeValue);
  277. return new Vector3(pX, pY);
  278. case MarkLineType.None:
  279. if (data.zeroPosition)
  280. {
  281. data.runtimeValue = 0;
  282. return grid.context.position;
  283. }
  284. else
  285. {
  286. pX = data.xPosition != 0 ? grid.context.x + data.xPosition :
  287. GetAxisPosition(grid, xAxis, dataZoom, serieDataCount, data.xValue);
  288. pY = data.yPosition != 0 ? grid.context.y + data.yPosition :
  289. GetAxisPosition(grid, yAxis, dataZoom, serieDataCount, data.yValue);
  290. data.runtimeValue = data.yValue;
  291. return new Vector3(pX, pY);
  292. }
  293. default:
  294. return grid.context.position;
  295. }
  296. }
  297. }
  298. }