CandlestickHandler.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using XUGL;
  5. namespace XCharts.Runtime
  6. {
  7. [UnityEngine.Scripting.Preserve]
  8. internal sealed class CandlestickHandler : SerieHandler<Candlestick>
  9. {
  10. public override void DrawSerie(VertexHelper vh)
  11. {
  12. DrawCandlestickSerie(vh, serie);
  13. }
  14. public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
  15. string marker, string itemFormatter, string numericFormatter, string ignoreDataDefaultContent,
  16. ref List<SerieParams> paramList, ref string title)
  17. {
  18. if (dataIndex < 0)
  19. dataIndex = serie.context.pointerItemDataIndex;
  20. if (dataIndex < 0)
  21. return;
  22. var serieData = serie.GetSerieData(dataIndex);
  23. if (serieData == null)
  24. return;
  25. title = category;
  26. var color = chart.GetMarkColor(serie, serieData);
  27. var newMarker = SerieHelper.GetItemMarker(serie, serieData, marker);
  28. var newItemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
  29. var newNumericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
  30. var param = serie.context.param;
  31. param.serieName = serie.serieName;
  32. param.serieIndex = serie.index;
  33. param.category = category;
  34. param.dimension = 1;
  35. param.serieData = serieData;
  36. param.dataCount = serie.dataCount;
  37. param.value = 0;
  38. param.total = 0;
  39. param.color = color;
  40. param.marker = newMarker;
  41. param.itemFormatter = newItemFormatter;
  42. param.numericFormatter = newNumericFormatter;
  43. param.columns.Clear();
  44. param.columns.Add(param.marker);
  45. param.columns.Add(serie.serieName);
  46. param.columns.Add(string.Empty);
  47. paramList.Add(param);
  48. for (int i = 1; i < 5; i++)
  49. {
  50. param = new SerieParams();
  51. param.serieName = serie.serieName;
  52. param.serieIndex = serie.index;
  53. param.dimension = i;
  54. param.serieData = serieData;
  55. param.dataCount = serie.dataCount;
  56. param.value = serieData.GetData(i);
  57. param.total = SerieHelper.GetMaxData(serie, i);
  58. param.color = color;
  59. param.marker = newMarker;
  60. param.itemFormatter = newItemFormatter;
  61. param.numericFormatter = newNumericFormatter;
  62. param.columns.Clear();
  63. param.columns.Add(param.marker);
  64. param.columns.Add(XCSettings.lang.GetCandlestickDimensionName(i - 1));
  65. param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
  66. paramList.Add(param);
  67. }
  68. }
  69. private void DrawCandlestickSerie(VertexHelper vh, Candlestick serie)
  70. {
  71. if (!serie.show) return;
  72. if (serie.animation.HasFadeOut()) return;
  73. XAxis xAxis;
  74. YAxis yAxis;
  75. GridCoord grid;
  76. if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
  77. if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
  78. if (!chart.TryGetChartComponent<GridCoord>(out grid, xAxis.gridIndex)) return;
  79. var theme = chart.theme;
  80. var dataZoom = chart.GetDataZoomOfAxis(xAxis);
  81. var showData = serie.GetDataList(dataZoom);
  82. float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, showData.Count, dataZoom);
  83. float barWidth = serie.GetBarWidth(categoryWidth);
  84. float gap = (categoryWidth - barWidth) / 2;
  85. int maxCount = serie.maxShow > 0 ?
  86. (serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
  87. showData.Count;
  88. bool dataChanging = false;
  89. float dataChangeDuration = serie.animation.GetChangeDuration();
  90. var dataAddDuration = serie.animation.GetAdditionDuration();
  91. var unscaledTime = serie.animation.unscaledTime;
  92. double yMinValue = yAxis.context.minValue;
  93. double yMaxValue = yAxis.context.maxValue;
  94. var isYAxis = false;
  95. serie.containerIndex = grid.index;
  96. serie.containterInstanceId = grid.instanceId;
  97. var intensive = grid.context.width / (maxCount - serie.minShow) < 0.6f;
  98. for (int i = serie.minShow; i < maxCount; i++)
  99. {
  100. var serieData = showData[i];
  101. if (!serieData.show || serie.IsIgnoreValue(serieData))
  102. {
  103. serie.context.dataPoints.Add(Vector3.zero);
  104. serie.context.dataIndexs.Add(serieData.index);
  105. continue;
  106. }
  107. var state = SerieHelper.GetSerieState(serie, serieData);
  108. var itemStyle = SerieHelper.GetItemStyle(serie, serieData, state);
  109. var startDataIndex = serieData.data.Count > 4 ? 1 : 0;
  110. var open = serieData.GetCurrData(startDataIndex, dataAddDuration, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue, unscaledTime);
  111. var close = serieData.GetCurrData(startDataIndex + 1, dataAddDuration, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue, unscaledTime);
  112. var lowest = serieData.GetCurrData(startDataIndex + 2, dataAddDuration, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue, unscaledTime);
  113. var heighest = serieData.GetCurrData(startDataIndex + 3, dataAddDuration, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue, unscaledTime);
  114. var isRise = yAxis.inverse ? close<open : close> open;
  115. var borderWidth = open == 0 ? 0f :
  116. (itemStyle.borderWidth == 0 ? theme.serie.candlestickBorderWidth :
  117. itemStyle.borderWidth);
  118. if (serieData.IsDataChanged()) dataChanging = true;
  119. float pX = grid.context.x + i * categoryWidth;
  120. float zeroY = grid.context.y + yAxis.context.offset;
  121. if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
  122. float pY = zeroY;
  123. var barHig = 0f;
  124. double valueTotal = yMaxValue - yMinValue;
  125. var minCut = (yMinValue > 0 ? yMinValue : 0);
  126. if (valueTotal != 0)
  127. {
  128. barHig = (float) ((close - open) / valueTotal * grid.context.height);
  129. pY += (float) ((open - minCut) / valueTotal * grid.context.height);
  130. }
  131. serieData.context.stackHeight = barHig;
  132. float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
  133. Vector3 plb, plt, prt, prb, top;
  134. plb = new Vector3(pX + gap + borderWidth, pY + borderWidth);
  135. plt = new Vector3(pX + gap + borderWidth, pY + currHig - borderWidth);
  136. prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig - borderWidth);
  137. prb = new Vector3(pX + gap + barWidth - borderWidth, pY + borderWidth);
  138. top = new Vector3(pX + gap + barWidth / 2, pY + currHig - borderWidth);
  139. if (serie.clip)
  140. {
  141. plb = chart.ClampInGrid(grid, plb);
  142. plt = chart.ClampInGrid(grid, plt);
  143. prt = chart.ClampInGrid(grid, prt);
  144. prb = chart.ClampInGrid(grid, prb);
  145. top = chart.ClampInGrid(grid, top);
  146. }
  147. serie.context.dataPoints.Add(top);
  148. serie.context.dataIndexs.Add(serieData.index);
  149. var areaColor = isRise ?
  150. itemStyle.GetColor(theme.serie.candlestickColor) :
  151. itemStyle.GetColor0(theme.serie.candlestickColor0);
  152. var borderColor = isRise ?
  153. itemStyle.GetBorderColor(theme.serie.candlestickBorderColor) :
  154. itemStyle.GetBorderColor0(theme.serie.candlestickBorderColor0);
  155. var itemWidth = Mathf.Abs(prt.x - plb.x);
  156. var itemHeight = Mathf.Abs(plt.y - prb.y);
  157. var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
  158. var lowPos = new Vector3(center.x, zeroY + (float) ((lowest - minCut) / valueTotal * grid.context.height));
  159. var heighPos = new Vector3(center.x, zeroY + (float) ((heighest - minCut) / valueTotal * grid.context.height));
  160. var openCenterPos = new Vector3(center.x, prb.y);
  161. var closeCenterPos = new Vector3(center.x, prt.y);
  162. if (intensive)
  163. {
  164. UGL.DrawLine(vh, lowPos, heighPos, borderWidth, borderColor);
  165. }
  166. else
  167. {
  168. if (barWidth > 2f * borderWidth)
  169. {
  170. if (itemWidth > 0 && itemHeight > 0)
  171. {
  172. if (itemStyle.IsNeedCorner())
  173. {
  174. UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
  175. itemStyle.cornerRadius, isYAxis, 0.5f);
  176. }
  177. else
  178. {
  179. chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
  180. serie.clip, grid);
  181. }
  182. UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
  183. itemStyle.cornerRadius, isYAxis, 0.5f);
  184. }
  185. }
  186. else
  187. {
  188. UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
  189. }
  190. if (isRise)
  191. {
  192. UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
  193. UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
  194. }
  195. else
  196. {
  197. UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
  198. UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
  199. }
  200. }
  201. }
  202. if (!serie.animation.IsFinish())
  203. {
  204. serie.animation.CheckProgress();
  205. }
  206. if (dataChanging)
  207. {
  208. chart.RefreshPainter(serie);
  209. }
  210. }
  211. }
  212. }