Няма описание
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.

LineHandler.GridCoord.cs 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. /// <summary>
  9. /// For grid coord
  10. /// </summary>
  11. internal sealed partial class LineHandler : SerieHandler<Line>
  12. {
  13. List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
  14. private GridCoord m_SerieGrid;
  15. public override Vector3 GetSerieDataLabelOffset(SerieData serieData, LabelStyle label)
  16. {
  17. var invert = label.autoOffset &&
  18. SerieHelper.IsDownPoint(serie, serieData.index) &&
  19. (serie.areaStyle == null || !serie.areaStyle.show);
  20. if (invert)
  21. {
  22. var offset = label.GetOffset(serie.context.insideRadius);
  23. return new Vector3(offset.x, -offset.y, offset.z);
  24. }
  25. else
  26. {
  27. return label.GetOffset(serie.context.insideRadius);
  28. }
  29. }
  30. private void UpdateSerieGridContext()
  31. {
  32. if (m_SerieGrid == null)
  33. return;
  34. var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
  35. if (!needCheck)
  36. {
  37. if (m_LastCheckContextFlag != needCheck)
  38. {
  39. m_LastCheckContextFlag = needCheck;
  40. serie.context.pointerItemDataIndex = -1;
  41. serie.context.pointerEnter = false;
  42. serie.highlight = false;
  43. serie.ResetInteract();
  44. foreach (var serieData in serie.data)
  45. serieData.context.highlight = false;
  46. if (SeriesHelper.IsStack(chart.series))
  47. chart.RefreshTopPainter();
  48. else
  49. chart.RefreshPainter(serie);
  50. }
  51. return;
  52. }
  53. m_LastCheckContextFlag = needCheck;
  54. var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
  55. var themeSymbolSize = chart.theme.serie.lineSymbolSize;
  56. var needInteract = false;
  57. serie.ResetDataIndex();
  58. if (m_LegendEnter)
  59. {
  60. serie.context.pointerEnter = true;
  61. serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
  62. for (int i = 0; i < serie.dataCount; i++)
  63. {
  64. var serieData = serie.data[i];
  65. var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, SerieState.Emphasis);
  66. serieData.context.highlight = true;
  67. serieData.interact.SetValue(ref needInteract, size);
  68. }
  69. }
  70. else if (serie.context.isTriggerByAxis)
  71. {
  72. serie.context.pointerEnter = false;
  73. serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
  74. for (int i = 0; i < serie.dataCount; i++)
  75. {
  76. var serieData = serie.data[i];
  77. var highlight = i == serie.context.pointerItemDataIndex;
  78. serieData.context.highlight = highlight;
  79. var state = SerieHelper.GetSerieState(serie, serieData, true);
  80. var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, state);
  81. serieData.interact.SetValue(ref needInteract, size);
  82. if (highlight)
  83. {
  84. serie.context.pointerEnter = true;
  85. serie.context.pointerItemDataIndex = i;
  86. needInteract = true;
  87. }
  88. }
  89. }
  90. else
  91. {
  92. var lastIndex = serie.context.pointerItemDataIndex;
  93. serie.context.pointerItemDataIndex = -1;
  94. serie.context.pointerEnter = false;
  95. for (int i = 0; i < serie.dataCount; i++)
  96. {
  97. var serieData = serie.data[i];
  98. var dist = Vector3.Distance(chart.pointerPos, serieData.context.position);
  99. var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize);
  100. var highlight = dist <= size;
  101. serieData.context.highlight = highlight;
  102. var state = SerieHelper.GetSerieState(serie, serieData, true);
  103. size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, state);
  104. serieData.interact.SetValue(ref needInteract, size);
  105. if (highlight)
  106. {
  107. serie.context.pointerEnter = true;
  108. serie.context.pointerItemDataIndex = serieData.index;
  109. }
  110. }
  111. if (lastIndex != serie.context.pointerItemDataIndex)
  112. {
  113. needInteract = true;
  114. }
  115. if (serie.context.pointerItemDataIndex >= 0)
  116. serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
  117. else
  118. serie.interact.SetValue(ref needInteract, lineWidth);
  119. }
  120. if (needInteract)
  121. {
  122. if (SeriesHelper.IsStack(chart.series))
  123. chart.RefreshTopPainter();
  124. else
  125. chart.RefreshPainter(serie);
  126. }
  127. }
  128. private void DrawLinePoint(VertexHelper vh, Serie serie)
  129. {
  130. if (!serie.show || serie.IsPerformanceMode())
  131. return;
  132. if (m_SerieGrid == null)
  133. return;
  134. var count = serie.context.dataPoints.Count;
  135. var clip = SeriesHelper.IsAnyClipSerie(chart.series);
  136. var theme = chart.theme;
  137. var interacting = false;
  138. var lineArrow = serie.lineArrow;
  139. var visualMap = chart.GetVisualMapOfSerie(serie);
  140. var isVisualMapGradient = VisualMapHelper.IsNeedLineGradient(visualMap);
  141. Axis axis;
  142. Axis relativedAxis;
  143. chart.GetSerieGridCoordAxis(serie, out axis, out relativedAxis);
  144. for (int i = 0; i < count; i++)
  145. {
  146. var index = serie.context.dataIndexs[i];
  147. var serieData = serie.GetSerieData(index);
  148. if (serieData == null)
  149. continue;
  150. if (serieData.context.isClip)
  151. continue;
  152. var state = SerieHelper.GetSerieState(serie, serieData, true);
  153. var symbol = SerieHelper.GetSerieSymbol(serie, serieData, state);
  154. if (!symbol.show || !symbol.ShowSymbol(index, count))
  155. continue;
  156. var pos = serie.context.dataPoints[i];
  157. if (lineArrow != null && lineArrow.show)
  158. {
  159. if (lineArrow.position == LineArrow.Position.Start && i == 0)
  160. continue;
  161. if (lineArrow.position == LineArrow.Position.End && i == count - 1)
  162. continue;
  163. }
  164. if (ChartHelper.IsIngore(pos))
  165. continue;
  166. var symbolSize = 0f;
  167. if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
  168. {
  169. symbolSize = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, chart.theme.serie.lineSymbolSize, state);
  170. serieData.interact.SetValue(ref interacting, symbolSize);
  171. symbolSize = serie.animation.GetSysmbolSize(symbolSize);
  172. }
  173. float symbolBorder = 0f;
  174. float[] cornerRadius = null;
  175. Color32 symbolColor, symbolToColor, symbolEmptyColor, borderColor;
  176. SerieHelper.GetItemColor(out symbolColor, out symbolToColor, out symbolEmptyColor, serie, serieData, theme, serie.context.colorIndex);
  177. SerieHelper.GetSymbolInfo(out borderColor, out symbolBorder, out cornerRadius, serie, null, chart.theme, state);
  178. if (isVisualMapGradient)
  179. {
  180. symbolColor = VisualMapHelper.GetLineGradientColor(visualMap, pos, m_SerieGrid, axis, relativedAxis, symbolColor);
  181. symbolToColor = symbolColor;
  182. }
  183. chart.DrawClipSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
  184. symbolColor, symbolToColor, symbolEmptyColor, borderColor, symbol.gap, clip, cornerRadius, m_SerieGrid,
  185. i > 0 ? serie.context.dataPoints[i - 1] : m_SerieGrid.context.position);
  186. }
  187. if (interacting)
  188. {
  189. if (SeriesHelper.IsStack(chart.series))
  190. chart.RefreshTopPainter();
  191. else
  192. chart.RefreshPainter(serie);
  193. }
  194. }
  195. private void DrawLineArrow(VertexHelper vh, Serie serie)
  196. {
  197. if (!serie.show || serie.lineArrow == null || !serie.lineArrow.show)
  198. return;
  199. if (serie.context.dataPoints.Count < 2)
  200. return;
  201. var lineColor = SerieHelper.GetLineColor(serie, null, chart.theme, serie.context.colorIndex);
  202. var startPos = Vector3.zero;
  203. var arrowPos = Vector3.zero;
  204. var lineArrow = serie.lineArrow.arrow;
  205. var dataPoints = serie.context.drawPoints;
  206. switch (serie.lineArrow.position)
  207. {
  208. case LineArrow.Position.End:
  209. if (dataPoints.Count < 3)
  210. {
  211. startPos = dataPoints[dataPoints.Count - 2].position;
  212. arrowPos = dataPoints[dataPoints.Count - 1].position;
  213. }
  214. else
  215. {
  216. startPos = dataPoints[dataPoints.Count - 3].position;
  217. arrowPos = dataPoints[dataPoints.Count - 2].position;
  218. }
  219. UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
  220. lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
  221. break;
  222. case LineArrow.Position.Start:
  223. startPos = dataPoints[1].position;
  224. arrowPos = dataPoints[0].position;
  225. UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
  226. lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
  227. break;
  228. }
  229. }
  230. private void DrawLineSerie(VertexHelper vh, Line serie)
  231. {
  232. if (serie.animation.HasFadeOut())
  233. return;
  234. Axis axis;
  235. Axis relativedAxis;
  236. var isY = chart.GetSerieGridCoordAxis(serie, out axis, out relativedAxis);
  237. if (axis == null)
  238. return;
  239. if (relativedAxis == null)
  240. return;
  241. m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
  242. if (m_SerieGrid == null)
  243. return;
  244. if (m_EndLabel != null && !m_SerieGrid.context.endLabelList.Contains(m_EndLabel))
  245. {
  246. m_SerieGrid.context.endLabelList.Add(m_EndLabel);
  247. }
  248. var visualMap = chart.GetVisualMapOfSerie(serie);
  249. var dataZoom = chart.GetDataZoomOfAxis(axis);
  250. var showData = serie.GetDataList(dataZoom);
  251. if (showData.Count <= 0)
  252. return;
  253. var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
  254. var scaleWid = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
  255. int maxCount = serie.maxShow > 0 ?
  256. (serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
  257. showData.Count;
  258. int rate = LineHelper.GetDataAverageRate(serie, m_SerieGrid, maxCount, false);
  259. var totalAverage = serie.sampleAverage > 0 ?
  260. serie.sampleAverage :
  261. DataHelper.DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
  262. var dataChanging = false;
  263. var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  264. var unscaledTime = serie.animation.unscaledTime;
  265. var interacting = false;
  266. var lineWidth = LineHelper.GetLineWidth(ref interacting, serie, chart.theme.serie.lineWidth);
  267. axis.context.scaleWidth = scaleWid;
  268. serie.containerIndex = m_SerieGrid.index;
  269. serie.containterInstanceId = m_SerieGrid.instanceId;
  270. Serie lastSerie = null;
  271. var isStack = SeriesHelper.IsStack<Line>(chart.series, serie.stack);
  272. if (isStack)
  273. {
  274. lastSerie = SeriesHelper.GetLastStackSerie(chart.series, serie);
  275. SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
  276. }
  277. var lp = Vector3.zero;
  278. for (int i = serie.minShow; i < maxCount; i += rate)
  279. {
  280. var serieData = showData[i];
  281. var isIgnore = serie.IsIgnoreValue(serieData);
  282. if (isIgnore)
  283. {
  284. serieData.context.stackHeight = 0;
  285. serieData.context.position = Vector3.zero;
  286. if (serie.ignoreLineBreak && serie.context.dataIgnores.Count > 0)
  287. {
  288. serie.context.dataIgnores[serie.context.dataIgnores.Count - 1] = true;
  289. }
  290. }
  291. else
  292. {
  293. var np = Vector3.zero;
  294. var xValue = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
  295. var relativedValue = DataHelper.SampleValue(ref showData, serie.sampleType, rate, serie.minShow,
  296. maxCount, totalAverage, i, dataChangeDuration, ref dataChanging, relativedAxis, unscaledTime);
  297. serieData.context.stackHeight = GetDataPoint(isY, axis, relativedAxis, m_SerieGrid, xValue, relativedValue,
  298. i, scaleWid, isStack, ref np);
  299. serieData.context.isClip = false;
  300. if (serie.clip && !m_SerieGrid.Contains(np))
  301. {
  302. if (m_SerieGrid.BoundaryPoint(lp, np, ref np))
  303. {
  304. serieData.context.isClip = true;
  305. }
  306. }
  307. serie.context.dataIgnores.Add(false);
  308. serieData.context.position = np;
  309. serie.context.dataPoints.Add(np);
  310. serie.context.dataIndexs.Add(serieData.index);
  311. lp = np;
  312. }
  313. }
  314. if (dataChanging || interacting)
  315. chart.RefreshPainter(serie);
  316. if (serie.context.dataPoints.Count <= 0)
  317. return;
  318. serie.animation.InitProgress(serie.context.dataPoints, isY);
  319. VisualMapHelper.AutoSetLineMinMax(visualMap, serie, isY, axis, relativedAxis);
  320. LineHelper.UpdateSerieDrawPoints(serie, chart.settings, chart.theme, visualMap, lineWidth, isY);
  321. LineHelper.DrawSerieLineArea(vh, serie, lastSerie, chart.theme, visualMap, isY, axis, relativedAxis, m_SerieGrid);
  322. LineHelper.DrawSerieLine(vh, chart.theme, serie, visualMap, m_SerieGrid, axis, relativedAxis, lineWidth);
  323. serie.context.vertCount = vh.currentVertCount;
  324. if (!serie.animation.IsFinish())
  325. {
  326. serie.animation.CheckProgress();
  327. serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
  328. chart.RefreshPainter(serie);
  329. }
  330. }
  331. private float GetDataPoint(bool isY, Axis axis, Axis relativedAxis, GridCoord grid, double xValue,
  332. double yValue, int i, float scaleWid, bool isStack, ref Vector3 np)
  333. {
  334. float xPos, yPos;
  335. var gridXY = isY ? grid.context.x : grid.context.y;
  336. var valueHig = 0f;
  337. valueHig = AxisHelper.GetAxisValueDistance(grid, relativedAxis, scaleWid, yValue);
  338. valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
  339. if (isY)
  340. {
  341. xPos = gridXY + valueHig;
  342. yPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
  343. if (isStack)
  344. {
  345. for (int n = 0; n < m_StackSerieData.Count - 1; n++)
  346. xPos += m_StackSerieData[n][i].context.stackHeight;
  347. }
  348. }
  349. else
  350. {
  351. yPos = gridXY + valueHig;
  352. xPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
  353. if (isStack)
  354. {
  355. for (int n = 0; n < m_StackSerieData.Count - 1; n++)
  356. yPos += m_StackSerieData[n][i].context.stackHeight;
  357. }
  358. }
  359. np = new Vector3(xPos, yPos);
  360. return AxisHelper.GetAxisValueLength(grid, relativedAxis, scaleWid, yValue);
  361. }
  362. }
  363. }