SerieHelper.cs 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using UnityEngine;
  5. namespace XCharts.Runtime
  6. {
  7. public static partial class SerieHelper
  8. {
  9. public static double GetMinData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
  10. {
  11. double min = double.MaxValue;
  12. var dataList = serie.GetDataList(dataZoom);
  13. for (int i = 0; i < dataList.Count; i++)
  14. {
  15. var serieData = dataList[i];
  16. if (serieData.show && serieData.data.Count > dimension)
  17. {
  18. var value = serieData.data[dimension];
  19. if (value < min && !serie.IsIgnoreValue(serieData, value)) min = value;
  20. }
  21. }
  22. return min == double.MaxValue ? 0 : min;
  23. }
  24. public static SerieData GetMinSerieData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
  25. {
  26. double min = double.MaxValue;
  27. SerieData minData = null;
  28. var dataList = serie.GetDataList(dataZoom);
  29. for (int i = 0; i < dataList.Count; i++)
  30. {
  31. var serieData = dataList[i];
  32. if (serieData.show && serieData.data.Count > dimension)
  33. {
  34. var value = serieData.data[dimension];
  35. if (value < min && !serie.IsIgnoreValue(serieData, value))
  36. {
  37. min = value;
  38. minData = serieData;
  39. }
  40. }
  41. }
  42. return minData;
  43. }
  44. public static double GetMaxData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
  45. {
  46. double max = double.MinValue;
  47. var dataList = serie.GetDataList(dataZoom);
  48. for (int i = 0; i < dataList.Count; i++)
  49. {
  50. var serieData = dataList[i];
  51. if (serieData.show && serieData.data.Count > dimension)
  52. {
  53. var value = serieData.data[dimension];
  54. if (value > max && !serie.IsIgnoreValue(serieData, value)) max = value;
  55. }
  56. }
  57. return max == double.MinValue ? 0 : max;
  58. }
  59. public static SerieData GetMaxSerieData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
  60. {
  61. double max = double.MinValue;
  62. SerieData maxData = null;
  63. var dataList = serie.GetDataList(dataZoom);
  64. for (int i = 0; i < dataList.Count; i++)
  65. {
  66. var serieData = dataList[i];
  67. if (serieData.show && serieData.data.Count > dimension)
  68. {
  69. var value = serieData.data[dimension];
  70. if (value > max && !serie.IsIgnoreValue(serieData, value))
  71. {
  72. max = value;
  73. maxData = serieData;
  74. }
  75. }
  76. }
  77. return maxData;
  78. }
  79. public static double GetAverageData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
  80. {
  81. double total = 0;
  82. var dataList = serie.GetDataList(dataZoom);
  83. for (int i = 0; i < dataList.Count; i++)
  84. {
  85. var serieData = dataList[i];
  86. if (serieData.show && serieData.data.Count > dimension)
  87. {
  88. var value = serieData.data[dimension];
  89. if (!serie.IsIgnoreValue(serieData, value))
  90. total += value;
  91. }
  92. }
  93. return total != 0 ? total / dataList.Count : 0;
  94. }
  95. private static List<double> s_TempList = new List<double>();
  96. public static double GetMedianData(Serie serie, int dimension = 1, DataZoom dataZoom = null)
  97. {
  98. s_TempList.Clear();
  99. var dataList = serie.GetDataList(dataZoom);
  100. for (int i = 0; i < dataList.Count; i++)
  101. {
  102. var serieData = dataList[i];
  103. if (serieData.show && serieData.data.Count > dimension)
  104. {
  105. var value = serieData.data[dimension];
  106. if (!serie.IsIgnoreValue(serieData, value))
  107. s_TempList.Add(value);
  108. }
  109. }
  110. s_TempList.Sort();
  111. var n = s_TempList.Count;
  112. if (n % 2 == 0) return (s_TempList[n / 2] + s_TempList[n / 2 - 1]) / 2;
  113. else return s_TempList[n / 2];
  114. }
  115. /// <summary>
  116. /// Gets the maximum and minimum values of the specified dimension of a serie.
  117. /// ||获得系列指定维数的最大最小值。
  118. /// </summary>
  119. /// <param name="serie">指定系列</param>
  120. /// <param name="dimension">指定维数</param>
  121. /// <param name="min">最小值</param>
  122. /// <param name="max">最大值</param>
  123. /// <param name="dataZoom">缩放组件,默认null</param>
  124. public static void GetMinMaxData(Serie serie, int dimension, out double min, out double max,
  125. DataZoom dataZoom = null)
  126. {
  127. max = double.MinValue;
  128. min = double.MaxValue;
  129. var dataList = serie.GetDataList(dataZoom);
  130. for (int i = 0; i < dataList.Count; i++)
  131. {
  132. var serieData = dataList[i];
  133. if (serieData.show && serieData.data.Count > dimension)
  134. {
  135. var value = serieData.data[dimension];
  136. if (!serie.IsIgnoreValue(serieData, value))
  137. {
  138. if (value > max) max = value;
  139. if (value < min) min = value;
  140. }
  141. }
  142. }
  143. if (min == double.MaxValue && max == double.MinValue)
  144. {
  145. min = 0;
  146. max = 0;
  147. }
  148. }
  149. /// <summary>
  150. /// Gets the maximum and minimum values of all data in the serie.
  151. /// ||获得系列所有数据的最大最小值。
  152. /// </summary>
  153. /// <param name="serie"></param>
  154. /// <param name="min"></param>
  155. /// <param name="max"></param>
  156. /// <param name="dataZoom"></param>
  157. public static void GetMinMaxData(Serie serie, out double min, out double max, DataZoom dataZoom = null, int dimension = 0)
  158. {
  159. max = double.MinValue;
  160. min = double.MaxValue;
  161. var dataList = serie.GetDataList(dataZoom);
  162. for (int i = 0; i < dataList.Count; i++)
  163. {
  164. var serieData = dataList[i];
  165. if (serieData.show)
  166. {
  167. var count = 0;
  168. if (dimension > 0) count = dimension;
  169. else count = serie.showDataDimension > serieData.data.Count ?
  170. serieData.data.Count :
  171. serie.showDataDimension;
  172. for (int j = 0; j < count; j++)
  173. {
  174. var value = serieData.data[j];
  175. if (!serie.IsIgnoreValue(serieData, value))
  176. {
  177. if (value > max) max = value;
  178. if (value < min) min = value;
  179. }
  180. }
  181. }
  182. }
  183. if (min == double.MaxValue && max == double.MinValue)
  184. {
  185. min = 0;
  186. max = 0;
  187. }
  188. }
  189. /// <summary>
  190. /// Whether the data for the specified dimension of serie are all 0.
  191. /// ||系列指定维数的数据是否全部为0。
  192. /// </summary>
  193. /// <param name="serie">系列</param>
  194. /// <param name="dimension">指定维数</param>
  195. /// <returns></returns>
  196. public static bool IsAllZeroValue(Serie serie, int dimension = 1)
  197. {
  198. if (serie.dataCount == 0) return false;
  199. foreach (var serieData in serie.data)
  200. {
  201. if (serieData.GetData(dimension) != 0) return false;
  202. }
  203. return true;
  204. }
  205. /// <summary>
  206. /// 更新运行时中心点和半径
  207. /// </summary>
  208. /// <param name="chartWidth"></param>
  209. /// <param name="chartHeight"></param>
  210. public static void UpdateCenter(Serie serie, BaseChart chart)
  211. {
  212. if (serie.center.Length < 2) return;
  213. var chartPosition = chart.chartPosition;
  214. var chartWidth = chart.chartWidth;
  215. var chartHeight = chart.chartHeight;
  216. if (serie.gridIndex >= 0)
  217. {
  218. var layout = chart.GetChartComponent<GridLayout>(0);
  219. if (layout != null)
  220. {
  221. layout.UpdateGridContext(serie.gridIndex, ref chartPosition, ref chartWidth, ref chartHeight);
  222. }
  223. }
  224. var centerX = serie.center[0] <= 1 ? chartWidth * serie.center[0] : serie.center[0];
  225. var centerY = serie.center[1] <= 1 ? chartHeight * serie.center[1] : serie.center[1];
  226. serie.context.center = chartPosition + new Vector3(centerX, centerY);
  227. var minWidth = Mathf.Min(chartWidth, chartHeight);
  228. serie.context.insideRadius = serie.radius[0] <= 1 ? minWidth * serie.radius[0] : serie.radius[0];
  229. serie.context.outsideRadius = serie.radius[1] <= 1 ? minWidth * serie.radius[1] : serie.radius[1];
  230. }
  231. public static void UpdateRect(Serie serie, Vector3 chartPosition, float chartWidth, float chartHeight)
  232. {
  233. if (serie.left != 0 || serie.right != 0 || serie.top != 0 || serie.bottom != 0)
  234. {
  235. var runtimeLeft = serie.left <= 1 ? serie.left * chartWidth : serie.left;
  236. var runtimeBottom = serie.bottom <= 1 ? serie.bottom * chartHeight : serie.bottom;
  237. var runtimeTop = serie.top <= 1 ? serie.top * chartHeight : serie.top;
  238. var runtimeRight = serie.right <= 1 ? serie.right * chartWidth : serie.right;
  239. serie.context.x = chartPosition.x + runtimeLeft;
  240. serie.context.y = chartPosition.y + runtimeBottom;
  241. serie.context.width = chartWidth - runtimeLeft - runtimeRight;
  242. serie.context.height = chartHeight - runtimeTop - runtimeBottom;
  243. serie.context.center = new Vector3(serie.context.x + serie.context.width / 2,
  244. serie.context.y + serie.context.height / 2);
  245. serie.context.rect = new Rect(serie.context.x, serie.context.y, serie.context.width, serie.context.height);
  246. }
  247. else
  248. {
  249. serie.context.x = chartPosition.x;
  250. serie.context.y = chartPosition.y;
  251. serie.context.width = chartWidth;
  252. serie.context.height = chartHeight;
  253. serie.context.center = chartPosition + new Vector3(chartWidth / 2, chartHeight / 2);
  254. serie.context.rect = new Rect(serie.context.x, serie.context.y, serie.context.width, serie.context.height);
  255. }
  256. }
  257. public static SerieState GetSerieState(Serie serie)
  258. {
  259. if (serie.highlight) return SerieState.Emphasis;
  260. return serie.state;
  261. }
  262. public static SerieState GetSerieState(SerieData serieData)
  263. {
  264. if (serieData.context.highlight) return SerieState.Emphasis;
  265. return serieData.state;
  266. }
  267. public static SerieState GetSerieState(Serie serie, SerieData serieData, bool defaultSerieState = false)
  268. {
  269. if (serieData == null) return GetSerieState(serie);
  270. if (serieData.context.highlight) return SerieState.Emphasis;
  271. if (serieData.state == SerieState.Auto) return defaultSerieState ? serie.state : GetSerieState(serie);
  272. return serieData.state;
  273. }
  274. public static Color32 GetItemBackgroundColor(Serie serie, SerieData serieData, ThemeStyle theme, int index,
  275. SerieState state = SerieState.Auto, bool useDefault = false)
  276. {
  277. var color = ChartConst.clearColor32;
  278. var stateStyle = GetStateStyle(serie, serieData, state);
  279. if (stateStyle == null)
  280. color = GetItemStyle(serie, serieData, SerieState.Normal).backgroundColor;
  281. else
  282. color = stateStyle.itemStyle.backgroundColor;
  283. if (useDefault && ChartHelper.IsClearColor(color))
  284. {
  285. color = theme.GetColor(index);
  286. color.a = 50;
  287. }
  288. return color;
  289. }
  290. public static void GetItemColor(out Color32 color, out Color32 toColor,
  291. Serie serie, SerieData serieData, ThemeStyle theme, SerieState state = SerieState.Auto)
  292. {
  293. var colorIndex = serieData != null && serie.colorByData ? serieData.index : serie.context.colorIndex;
  294. GetItemColor(out color, out toColor, serie, serieData, theme, colorIndex, state, true);
  295. }
  296. public static void GetItemColor(out Color32 color, out Color32 toColor,
  297. Serie serie, SerieData serieData, ThemeStyle theme, int index, SerieState state = SerieState.Auto, bool opacity = true)
  298. {
  299. color = ColorUtil.clearColor32;
  300. toColor = ColorUtil.clearColor32;
  301. if (serie == null) return;
  302. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  303. var stateStyle = GetStateStyle(serie, serieData, state);
  304. if (stateStyle == null)
  305. {
  306. var style = GetItemStyle(serie, serieData, SerieState.Normal);
  307. GetColor(ref color, style.color, style.color, style.opacity, theme, index, opacity);
  308. GetColor(ref toColor, style.toColor, color, style.opacity, theme, index, opacity);
  309. switch (state)
  310. {
  311. case SerieState.Emphasis:
  312. color = ChartHelper.GetHighlightColor(color);
  313. toColor = ChartHelper.GetHighlightColor(toColor);
  314. break;
  315. case SerieState.Blur:
  316. color = ChartHelper.GetBlurColor(color);
  317. toColor = ChartHelper.GetBlurColor(toColor);
  318. break;
  319. case SerieState.Select:
  320. color = ChartHelper.GetSelectColor(color);
  321. toColor = ChartHelper.GetSelectColor(toColor);
  322. break;
  323. default:
  324. break;
  325. }
  326. }
  327. else
  328. {
  329. GetColor(ref color, stateStyle.itemStyle.color, stateStyle.itemStyle.color, stateStyle.itemStyle.opacity, theme, index, opacity);
  330. GetColor(ref toColor, stateStyle.itemStyle.toColor, color, stateStyle.itemStyle.opacity, theme, index, opacity);
  331. }
  332. }
  333. public static void GetItemColor(out Color32 color, out Color32 toColor, out Color32 backgroundColor,
  334. Serie serie, SerieData serieData, ThemeStyle theme, int index, SerieState state = SerieState.Auto, bool opacity = true)
  335. {
  336. color = ColorUtil.clearColor32;
  337. toColor = ColorUtil.clearColor32;
  338. backgroundColor = ColorUtil.clearColor32;
  339. if (serie == null) return;
  340. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  341. var stateStyle = GetStateStyle(serie, serieData, state);
  342. if (stateStyle == null)
  343. {
  344. var style = GetItemStyle(serie, serieData, SerieState.Normal);
  345. GetColor(ref color, style.color, style.color, style.opacity, theme, index, opacity);
  346. GetColor(ref toColor, style.toColor, color, style.opacity, theme, index, opacity);
  347. backgroundColor = style.backgroundColor;
  348. switch (state)
  349. {
  350. case SerieState.Emphasis:
  351. color = ChartHelper.GetHighlightColor(color);
  352. toColor = ChartHelper.GetHighlightColor(toColor);
  353. break;
  354. case SerieState.Blur:
  355. color = ChartHelper.GetBlurColor(color);
  356. toColor = ChartHelper.GetBlurColor(toColor);
  357. break;
  358. case SerieState.Select:
  359. color = ChartHelper.GetSelectColor(color);
  360. toColor = ChartHelper.GetSelectColor(toColor);
  361. break;
  362. default:
  363. break;
  364. }
  365. }
  366. else
  367. {
  368. backgroundColor = stateStyle.itemStyle.backgroundColor;
  369. GetColor(ref color, stateStyle.itemStyle.color, stateStyle.itemStyle.color, stateStyle.itemStyle.opacity, theme, index, opacity);
  370. GetColor(ref toColor, stateStyle.itemStyle.toColor, color, stateStyle.itemStyle.opacity, theme, index, opacity);
  371. }
  372. }
  373. public static Color32 GetItemColor(Serie serie, SerieData serieData, ThemeStyle theme, int index, SerieState state = SerieState.Auto, bool opacity = true)
  374. {
  375. var color = ColorUtil.clearColor32;
  376. if (serie == null) return color;
  377. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  378. var stateStyle = GetStateStyle(serie, serieData, state);
  379. if (stateStyle == null || !stateStyle.itemStyle.show)
  380. {
  381. var style = GetItemStyle(serie, serieData);
  382. GetColor(ref color, style.color, style.color, style.opacity, theme, index, opacity);
  383. switch (state)
  384. {
  385. case SerieState.Emphasis:
  386. color = ChartHelper.GetHighlightColor(color);
  387. break;
  388. case SerieState.Blur:
  389. color = ChartHelper.GetBlurColor(color);
  390. break;
  391. case SerieState.Select:
  392. color = ChartHelper.GetSelectColor(color);
  393. break;
  394. default:
  395. break;
  396. }
  397. }
  398. else
  399. {
  400. GetColor(ref color, stateStyle.itemStyle.color, stateStyle.itemStyle.color, stateStyle.itemStyle.opacity, theme, index, opacity);
  401. }
  402. return color;
  403. }
  404. public static bool IsDownPoint(Serie serie, int index)
  405. {
  406. var dataPoints = serie.context.dataPoints;
  407. if (dataPoints.Count < 2) return false;
  408. else if (index > 0 && index < dataPoints.Count - 1)
  409. {
  410. var lp = dataPoints[index - 1];
  411. var np = dataPoints[index + 1];
  412. var cp = dataPoints[index];
  413. var dot = Vector3.Cross(np - lp, cp - np);
  414. return dot.z < 0;
  415. }
  416. else if (index == 0)
  417. {
  418. return dataPoints[0].y < dataPoints[1].y;
  419. }
  420. else if (index == dataPoints.Count - 1)
  421. {
  422. return dataPoints[index].y < dataPoints[index - 1].y;
  423. }
  424. else
  425. {
  426. return false;
  427. }
  428. }
  429. public static ItemStyle GetItemStyle(Serie serie, SerieData serieData, SerieState state = SerieState.Auto)
  430. {
  431. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  432. var stateStyle = GetStateStyle(serie, serieData, state);
  433. if (stateStyle == null || !stateStyle.show)
  434. {
  435. return serieData != null && serieData.itemStyle != null ? serieData.itemStyle : serie.itemStyle;
  436. }
  437. else
  438. {
  439. return stateStyle.itemStyle;
  440. }
  441. }
  442. public static LabelStyle GetSerieLabel(Serie serie, SerieData serieData, SerieState state = SerieState.Auto)
  443. {
  444. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  445. if (state == SerieState.Normal)
  446. {
  447. return serieData != null && serieData.labelStyle != null ? serieData.labelStyle : serie.label;
  448. }
  449. else
  450. {
  451. var stateStyle = GetStateStyle(serie, serieData, state);
  452. if (stateStyle != null && stateStyle.show) return stateStyle.label;
  453. else if (serieData.labelStyle != null) return serieData.labelStyle;
  454. else return serie.label;
  455. }
  456. }
  457. public static LabelLine GetSerieLabelLine(Serie serie, SerieData serieData, SerieState state = SerieState.Auto)
  458. {
  459. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  460. if (state == SerieState.Normal)
  461. {
  462. return serieData != null && serieData.labelLine != null ? serieData.labelLine : serie.labelLine;
  463. }
  464. else
  465. {
  466. var stateStyle = GetStateStyle(serie, serieData, state);
  467. if (stateStyle != null && stateStyle.show) return stateStyle.labelLine;
  468. else if (serieData.labelLine != null) return serieData.labelLine;
  469. else return serie.labelLine;
  470. }
  471. }
  472. public static SerieSymbol GetSerieSymbol(Serie serie, SerieData serieData, SerieState state = SerieState.Auto)
  473. {
  474. if (state == SerieState.Auto) state = GetSerieState(serie, serieData);
  475. if (state == SerieState.Normal)
  476. {
  477. return serieData != null && serieData.symbol != null ? serieData.symbol : serie.symbol;
  478. }
  479. else
  480. {
  481. var stateStyle = GetStateStyle(serie, serieData, state);
  482. if (stateStyle != null && stateStyle.show) return stateStyle.symbol;
  483. else if (serieData.symbol != null) return serieData.symbol;
  484. else return serie.symbol;
  485. }
  486. }
  487. public static LineStyle GetLineStyle(Serie serie, SerieData serieData)
  488. {
  489. if (serieData != null && serieData.lineStyle != null) return serieData.lineStyle;
  490. else return serie.lineStyle;
  491. }
  492. public static AreaStyle GetAreaStyle(Serie serie, SerieData serieData)
  493. {
  494. if (serieData != null && serieData.areaStyle != null) return serieData.areaStyle;
  495. else return serie.areaStyle;
  496. }
  497. public static TitleStyle GetTitleStyle(Serie serie, SerieData serieData)
  498. {
  499. if (serieData != null && serieData.titleStyle != null) return serieData.titleStyle;
  500. else return serie.titleStyle;
  501. }
  502. public static EmphasisStyle GetEmphasisStyle(Serie serie, SerieData serieData)
  503. {
  504. if (serieData != null && serieData.emphasisStyle != null) return serieData.emphasisStyle;
  505. else return serie.emphasisStyle;
  506. }
  507. public static BlurStyle GetBlurStyle(Serie serie, SerieData serieData)
  508. {
  509. if (serieData != null && serieData.blurStyle != null) return serieData.blurStyle;
  510. else return serie.blurStyle;
  511. }
  512. public static SelectStyle GetSelectStyle(Serie serie, SerieData serieData)
  513. {
  514. if (serieData != null && serieData.selectStyle != null) return serieData.selectStyle;
  515. else return serie.selectStyle;
  516. }
  517. public static StateStyle GetStateStyle(Serie serie, SerieData serieData, SerieState state)
  518. {
  519. switch (state)
  520. {
  521. case SerieState.Emphasis:
  522. return GetEmphasisStyle(serie, serieData);
  523. case SerieState.Blur:
  524. return GetBlurStyle(serie, serieData);
  525. case SerieState.Select:
  526. return GetSelectStyle(serie, serieData);
  527. default:
  528. return null;
  529. }
  530. }
  531. public static bool GetAreaColor(out Color32 color, out Color32 toColor,
  532. Serie serie, SerieData serieData, ThemeStyle theme, int index)
  533. {
  534. bool fill, toTop;
  535. return GetAreaColor(out color, out toColor, out fill, out toTop, serie, serieData, theme, index);
  536. }
  537. public static bool GetAreaColor(out Color32 color, out Color32 toColor, out bool innerFill,
  538. out bool toTop, Serie serie, SerieData serieData, ThemeStyle theme, int index)
  539. {
  540. color = ChartConst.clearColor32;
  541. toColor = ChartConst.clearColor32;
  542. innerFill = false;
  543. toTop = true;
  544. var state = GetSerieState(serie, serieData);
  545. var stateStyle = GetStateStyle(serie, serieData, state);
  546. if (stateStyle == null)
  547. {
  548. var areaStyle = GetAreaStyle(serie, serieData);
  549. if (areaStyle == null || !areaStyle.show) return false;
  550. innerFill = areaStyle.innerFill;
  551. toTop = areaStyle.toTop;
  552. GetColor(ref color, areaStyle.color, serie.itemStyle.color, areaStyle.opacity, theme, index);
  553. GetColor(ref toColor, areaStyle.toColor, color, areaStyle.opacity, theme, index);
  554. switch (state)
  555. {
  556. case SerieState.Emphasis:
  557. color = ChartHelper.GetHighlightColor(color);
  558. toColor = ChartHelper.GetHighlightColor(toColor);
  559. break;
  560. case SerieState.Blur:
  561. color = ChartHelper.GetBlurColor(color);
  562. toColor = ChartHelper.GetBlurColor(toColor);
  563. break;
  564. case SerieState.Select:
  565. color = ChartHelper.GetSelectColor(color);
  566. toColor = ChartHelper.GetSelectColor(toColor);
  567. break;
  568. default:
  569. break;
  570. }
  571. }
  572. else
  573. {
  574. if (stateStyle.areaStyle.show)
  575. {
  576. innerFill = stateStyle.areaStyle.innerFill;
  577. toTop = stateStyle.areaStyle.toTop;
  578. GetColor(ref color, stateStyle.areaStyle.color, stateStyle.itemStyle.color, stateStyle.areaStyle.opacity, theme, index);
  579. GetColor(ref toColor, stateStyle.areaStyle.toColor, color, stateStyle.areaStyle.opacity, theme, index);
  580. }
  581. else
  582. {
  583. return false;
  584. }
  585. }
  586. return true;
  587. }
  588. public static Color32 GetLineColor(Serie serie, SerieData serieData, ThemeStyle theme, int index, SerieState state = SerieState.Auto)
  589. {
  590. Color32 color = ChartConst.clearColor32;
  591. if (state == SerieState.Auto)
  592. state = GetSerieState(serie, serieData);
  593. var stateStyle = GetStateStyle(serie, serieData, state);
  594. if (stateStyle == null)
  595. {
  596. var lineStyle = GetLineStyle(serie, serieData);
  597. GetColor(ref color, lineStyle.color, serie.itemStyle.color, lineStyle.opacity, theme, index);
  598. switch (state)
  599. {
  600. case SerieState.Emphasis:
  601. return ChartHelper.GetHighlightColor(color);
  602. case SerieState.Blur:
  603. return ChartHelper.GetBlurColor(color);
  604. case SerieState.Select:
  605. return ChartHelper.GetSelectColor(color);
  606. default:
  607. return color;
  608. }
  609. }
  610. else
  611. {
  612. GetColor(ref color, stateStyle.lineStyle.color, stateStyle.itemStyle.color, stateStyle.lineStyle.opacity, theme, index);
  613. return color;
  614. }
  615. }
  616. public static void GetColor(ref Color32 color, Color32 checkColor, Color32 itemColor,
  617. float opacity, ThemeStyle theme, int colorIndex, bool setOpacity = true)
  618. {
  619. if (!ChartHelper.IsClearColor(checkColor)) color = checkColor;
  620. else if (!ChartHelper.IsClearColor(itemColor)) color = itemColor;
  621. if (ChartHelper.IsClearColor(color) && colorIndex >= 0) color = theme.GetColor(colorIndex);
  622. if (setOpacity) ChartHelper.SetColorOpacity(ref color, opacity);
  623. }
  624. public static void GetSymbolInfo(out Color32 borderColor, out float border, out float[] cornerRadius,
  625. Serie serie, SerieData serieData, ThemeStyle theme, SerieState state = SerieState.Auto)
  626. {
  627. borderColor = ChartConst.clearColor32;
  628. if (state == SerieState.Auto)
  629. state = GetSerieState(serie, serieData);
  630. var stateStyle = GetStateStyle(serie, serieData, state);
  631. if (stateStyle == null)
  632. {
  633. var itemStyle = GetItemStyle(serie, serieData, SerieState.Normal);
  634. border = itemStyle.borderWidth != 0 ? itemStyle.borderWidth : serie.lineStyle.GetWidth(theme.serie.lineWidth) * 1.8f;
  635. cornerRadius = itemStyle.cornerRadius;
  636. GetColor(ref borderColor, itemStyle.borderColor, itemStyle.borderColor, 1, theme, -1);
  637. switch (state)
  638. {
  639. case SerieState.Emphasis:
  640. borderColor = ChartHelper.GetHighlightColor(borderColor);
  641. break;
  642. case SerieState.Blur:
  643. borderColor = ChartHelper.GetBlurColor(borderColor);
  644. break;
  645. case SerieState.Select:
  646. borderColor = ChartHelper.GetSelectColor(borderColor);
  647. break;
  648. default:
  649. break;
  650. }
  651. }
  652. else
  653. {
  654. var itemStyle = stateStyle.itemStyle;
  655. border = itemStyle.borderWidth != 0 ? itemStyle.borderWidth : stateStyle.lineStyle.GetWidth(theme.serie.lineWidth) * 1.8f;
  656. cornerRadius = itemStyle.cornerRadius;
  657. GetColor(ref borderColor, stateStyle.itemStyle.borderColor, ColorUtil.clearColor32, 1, theme, -1);
  658. }
  659. }
  660. public static float GetSysmbolSize(Serie serie, SerieData serieData, float defaultSize, SerieState state = SerieState.Auto, bool checkAnimation = false)
  661. {
  662. if (serie == null) return defaultSize;
  663. if (state == SerieState.Auto)
  664. state = GetSerieState(serie, serieData);
  665. var stateStyle = GetStateStyle(serie, serieData, state);
  666. var size = 0f;
  667. if (stateStyle == null)
  668. {
  669. var symbol = GetSerieSymbol(serie, serieData, SerieState.Normal);
  670. size = symbol.GetSize(serieData == null ? null : serieData.data, defaultSize);
  671. switch (state)
  672. {
  673. case SerieState.Emphasis:
  674. case SerieState.Select:
  675. size = serie.animation.interaction.GetRadius(size);
  676. break;
  677. default:
  678. break;
  679. }
  680. }
  681. else
  682. {
  683. var symbol = stateStyle.symbol;
  684. size = symbol.GetSize(serieData == null ? null : serieData.data, defaultSize);
  685. }
  686. if (serieData != null && checkAnimation)
  687. {
  688. size = (float)serieData.GetAddAnimationData(0, size, serie.animation.GetAdditionDuration());
  689. }
  690. return size;
  691. }
  692. public static string GetNumericFormatter(Serie serie, SerieData serieData, string defaultFormatter = null)
  693. {
  694. var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
  695. if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
  696. else return defaultFormatter;
  697. }
  698. public static string GetItemFormatter(Serie serie, SerieData serieData, string defaultFormatter = null)
  699. {
  700. var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
  701. if (!string.IsNullOrEmpty(itemStyle.itemFormatter)) return itemStyle.itemFormatter;
  702. else return defaultFormatter;
  703. }
  704. public static string GetItemMarker(Serie serie, SerieData serieData, string defaultMarker = null)
  705. {
  706. var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
  707. if (!string.IsNullOrEmpty(itemStyle.itemMarker)) return itemStyle.itemMarker;
  708. else return defaultMarker;
  709. }
  710. /// <summary>
  711. /// 获得指定维数的最大最小值
  712. /// </summary>
  713. /// <param name="dimension"></param>
  714. /// <param name="dataZoom"></param>
  715. /// <returns></returns>
  716. public static void UpdateMinMaxData(Serie serie, int dimension, double ceilRate = 0, DataZoom dataZoom = null)
  717. {
  718. double min = 0, max = 0;
  719. GetMinMaxData(serie, dimension, out min, out max, dataZoom);
  720. if (ceilRate < 0)
  721. {
  722. serie.context.dataMin = min;
  723. serie.context.dataMax = max;
  724. }
  725. else
  726. {
  727. serie.context.dataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
  728. serie.context.dataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
  729. }
  730. }
  731. public static void GetAllMinMaxData(Serie serie, double ceilRate = 0, DataZoom dataZoom = null)
  732. {
  733. double min = 0, max = 0;
  734. GetMinMaxData(serie, out min, out max, dataZoom);
  735. if (ceilRate < 0)
  736. {
  737. serie.context.dataMin = min;
  738. serie.context.dataMax = max;
  739. }
  740. else
  741. {
  742. serie.context.dataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
  743. serie.context.dataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
  744. }
  745. }
  746. /// <summary>
  747. /// 根据dataZoom更新数据列表缓存
  748. /// </summary>
  749. /// <param name="dataZoom"></param>
  750. public static void UpdateFilterData(Serie serie, DataZoom dataZoom)
  751. {
  752. if (dataZoom == null || !dataZoom.enable)
  753. {
  754. serie.m_NeedUpdateFilterData = true;
  755. serie.context.dataZoomStartIndex = 0;
  756. serie.context.dataZoomStartIndexOffset = 0;
  757. return;
  758. }
  759. if (dataZoom.IsContainsXAxis(serie.xAxisIndex))
  760. {
  761. if (dataZoom.IsXAxisIndexValue(serie.xAxisIndex))
  762. {
  763. double min = 0, max = 0;
  764. dataZoom.GetXAxisIndexValue(serie.xAxisIndex, out min, out max);
  765. UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
  766. }
  767. else
  768. {
  769. UpdateFilterData_Category(serie, dataZoom);
  770. }
  771. }
  772. else if (dataZoom.IsContainsYAxis(serie.yAxisIndex))
  773. {
  774. if (dataZoom.IsYAxisIndexValue(serie.yAxisIndex))
  775. {
  776. double min = 0, max = 0;
  777. dataZoom.GetYAxisIndexValue(serie.yAxisIndex, out min, out max);
  778. UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
  779. }
  780. else
  781. {
  782. UpdateFilterData_Category(serie, dataZoom);
  783. }
  784. }
  785. }
  786. private static void UpdateFilterData_XAxisValue(Serie serie, DataZoom dataZoom, int dimension, double min, double max)
  787. {
  788. var data = serie.data;
  789. var startValue = min;
  790. var endValue = max;
  791. if (endValue < startValue) endValue = startValue;
  792. if (startValue != serie.m_FilterStartValue || endValue != serie.m_FilterEndValue ||
  793. dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
  794. {
  795. serie.m_FilterStartValue = startValue;
  796. serie.m_FilterEndValue = endValue;
  797. serie.m_FilterMinShow = dataZoom.minShowNum;
  798. serie.m_NeedUpdateFilterData = false;
  799. if (ReferenceEquals(serie.m_FilterData, data))
  800. {
  801. serie.m_FilterData = new List<SerieData>();
  802. }
  803. serie.m_FilterData.Clear();
  804. foreach (var serieData in data)
  805. {
  806. var value = serieData.GetData(dimension);
  807. if (value >= startValue && value <= endValue)
  808. {
  809. serie.m_FilterData.Add(serieData);
  810. }
  811. }
  812. }
  813. else if (endValue == 0)
  814. {
  815. if (serie.m_FilterData == null)
  816. serie.m_FilterData = new List<SerieData>();
  817. else if (serie.m_FilterData.Count > 0)
  818. serie.m_FilterData.Clear();
  819. }
  820. }
  821. private static void UpdateFilterData_Category(Serie serie, DataZoom dataZoom)
  822. {
  823. var data = serie.data;
  824. var range = Mathf.RoundToInt(data.Count * (dataZoom.end - dataZoom.start) / 100);
  825. if (range <= 0) range = 1;
  826. int start = 0, end = 0;
  827. if (dataZoom.context.invert)
  828. {
  829. end = Mathf.RoundToInt(data.Count * dataZoom.end / 100);
  830. start = end - range;
  831. if (start < 0) start = 0;
  832. }
  833. else
  834. {
  835. start = Mathf.RoundToInt(data.Count * dataZoom.start / 100);
  836. end = start + range;
  837. if (end > data.Count) end = data.Count;
  838. }
  839. if (start != serie.m_FilterStart || end != serie.m_FilterEnd ||
  840. dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
  841. {
  842. serie.m_FilterStart = start;
  843. serie.m_FilterEnd = end;
  844. serie.m_FilterMinShow = dataZoom.minShowNum;
  845. serie.m_NeedUpdateFilterData = false;
  846. if (data.Count > 0)
  847. {
  848. if (range < dataZoom.minShowNum)
  849. {
  850. if (dataZoom.minShowNum > data.Count) range = data.Count;
  851. else range = dataZoom.minShowNum;
  852. }
  853. if (range > data.Count - start)
  854. start = data.Count - range;
  855. if (start >= 0)
  856. {
  857. serie.context.dataZoomStartIndex = start;
  858. serie.context.dataZoomStartIndexOffset = 0;
  859. serie.m_FilterData = data.GetRange(start, range);
  860. var nowCount = serie.m_FilterData.Count;
  861. if (nowCount > 0)
  862. {
  863. if (serie.IsIgnoreValue(serie.m_FilterData[nowCount - 1]))
  864. {
  865. for (int i = start + range; i < data.Count; i++)
  866. {
  867. serie.m_FilterData.Add(data[i]);
  868. if (!serie.IsIgnoreValue(data[i]))
  869. break;
  870. }
  871. }
  872. if (serie.IsIgnoreValue(serie.m_FilterData[0]))
  873. {
  874. for (int i = start - 1; i >= 0; i--)
  875. {
  876. serie.m_FilterData.Insert(0, data[i]);
  877. serie.context.dataZoomStartIndexOffset++;
  878. if (!serie.IsIgnoreValue(data[i]))
  879. break;
  880. }
  881. }
  882. }
  883. }
  884. else
  885. {
  886. serie.context.dataZoomStartIndex = 0;
  887. serie.context.dataZoomStartIndexOffset = 0;
  888. serie.m_FilterData = data;
  889. }
  890. }
  891. else
  892. {
  893. serie.context.dataZoomStartIndex = 0;
  894. serie.context.dataZoomStartIndexOffset = 0;
  895. serie.m_FilterData = data;
  896. }
  897. }
  898. else if (end == 0)
  899. {
  900. serie.context.dataZoomStartIndex = 0;
  901. serie.context.dataZoomStartIndexOffset = 0;
  902. if (serie.m_FilterData == null)
  903. serie.m_FilterData = new List<SerieData>();
  904. else if (serie.m_FilterData.Count > 0)
  905. serie.m_FilterData.Clear();
  906. }
  907. }
  908. public static void UpdateSerieRuntimeFilterData(Serie serie, bool filterInvisible = true)
  909. {
  910. serie.context.sortedData.Clear();
  911. foreach (var serieData in serie.data)
  912. {
  913. if (!filterInvisible || (filterInvisible && serieData.show))
  914. serie.context.sortedData.Add(serieData);
  915. }
  916. switch (serie.dataSortType)
  917. {
  918. case SerieDataSortType.Ascending:
  919. serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2)
  920. {
  921. var value1 = data1.GetData(1);
  922. var value2 = data2.GetData(1);
  923. if (value1 == value2) return 0;
  924. else if (value1 > value2) return 1;
  925. else return -1;
  926. });
  927. break;
  928. case SerieDataSortType.Descending:
  929. serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2)
  930. {
  931. var value1 = data1.GetData(1);
  932. var value2 = data2.GetData(1);
  933. if (value1 == value2) return 0;
  934. else if (value1 > value2) return -1;
  935. else return 1;
  936. });
  937. break;
  938. case SerieDataSortType.None:
  939. break;
  940. }
  941. }
  942. public static T CloneSerie<T>(Serie serie) where T : Serie
  943. {
  944. var newSerie = Activator.CreateInstance<T>();
  945. SerieHelper.CopySerie(serie, newSerie);
  946. return newSerie;
  947. }
  948. public static void CopySerie(Serie oldSerie, Serie newSerie)
  949. {
  950. var fields = typeof(Serie).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  951. foreach (var field in fields)
  952. {
  953. if (field.IsDefined(typeof(SerializeField), false))
  954. {
  955. var filedValue = field.GetValue(oldSerie);
  956. if (filedValue == null) continue;
  957. var filedType = filedValue.GetType();
  958. if (filedType.IsClass)
  959. field.SetValue(newSerie, ReflectionUtil.DeepCloneSerializeField(filedValue));
  960. }
  961. }
  962. }
  963. }
  964. }