暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

SerieLabelHelper.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace XCharts.Runtime
  4. {
  5. public static class SerieLabelHelper
  6. {
  7. public static Color GetLabelColor(Serie serie, ThemeStyle theme, int index)
  8. {
  9. if (serie.label != null && !ChartHelper.IsClearColor(serie.label.textStyle.color))
  10. {
  11. return serie.label.textStyle.color;
  12. }
  13. else
  14. {
  15. return theme.GetColor(index);
  16. }
  17. }
  18. public static bool CanShowLabel(Serie serie, SerieData serieData, LabelStyle label, int dimesion)
  19. {
  20. return serie.show && serieData.context.canShowLabel && !serie.IsIgnoreValue(serieData, dimesion);
  21. }
  22. public static string GetFormatterContent(Serie serie, SerieData serieData,
  23. double dataValue, double dataTotal, LabelStyle serieLabel, Color color)
  24. {
  25. if (serieLabel == null)
  26. {
  27. serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
  28. }
  29. var numericFormatter = serieLabel == null ? "" : serieLabel.numericFormatter;
  30. var serieName = serie.serieName;
  31. var dataName = serieData != null ? serieData.name : null;
  32. if (string.IsNullOrEmpty(serieLabel.formatter))
  33. {
  34. var currentContent = ChartCached.NumberToStr(dataValue, numericFormatter);
  35. if (serieLabel.formatterFunction == null)
  36. return currentContent;
  37. else
  38. return serieLabel.formatterFunction(serieData.index, dataValue, null, currentContent);
  39. }
  40. else
  41. {
  42. var content = serieLabel.formatter;
  43. FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, serie.dataCount, dataValue,
  44. dataTotal, serieName, dataName, dataName, color, serieData);
  45. if (serieLabel.formatterFunction == null)
  46. return content;
  47. else
  48. return serieLabel.formatterFunction(serieData.index, dataValue, null, content);
  49. }
  50. }
  51. public static void SetGaugeLabelText(Serie serie)
  52. {
  53. var serieData = serie.GetSerieData(0);
  54. if (serieData == null) return;
  55. if (serieData.labelObject == null) return;
  56. var label = SerieHelper.GetSerieLabel(serie, serieData);
  57. if (label == null) return;
  58. var value = serieData.GetData(1);
  59. var total = serie.max;
  60. var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total, null, Color.clear);
  61. serieData.labelObject.SetText(content);
  62. serieData.labelObject.SetPosition(serie.context.center + label.offset);
  63. if (!ChartHelper.IsClearColor(label.textStyle.color))
  64. {
  65. serieData.labelObject.text.SetColor(label.textStyle.color);
  66. }
  67. }
  68. public static void UpdatePieLabelPosition(Serie serie, SerieData serieData)
  69. {
  70. if (serieData.labelObject == null) return;
  71. var startAngle = serie.context.startAngle;
  72. var currAngle = serieData.context.halfAngle;
  73. var currRad = currAngle * Mathf.Deg2Rad;
  74. var offsetRadius = serieData.context.offsetRadius;
  75. var insideRadius = serieData.context.insideRadius;
  76. var outsideRadius = serieData.context.outsideRadius;
  77. var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
  78. var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
  79. switch (serieLabel.position)
  80. {
  81. case LabelStyle.Position.Center:
  82. serieData.context.labelPosition = serie.context.center;
  83. break;
  84. case LabelStyle.Position.Inside:
  85. var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2 + serieLabel.distance;
  86. var labelCenter = new Vector2(serie.context.center.x + labelRadius * Mathf.Sin(currRad),
  87. serie.context.center.y + labelRadius * Mathf.Cos(currRad));
  88. serieData.context.labelPosition = labelCenter;
  89. break;
  90. default:
  91. //LabelStyle.Position.Outside
  92. if (labelLine != null && labelLine.lineType == LabelLine.LineType.HorizontalLine)
  93. {
  94. var radius1 = serie.context.outsideRadius;
  95. var radius3 = insideRadius + (outsideRadius - insideRadius) / 2;
  96. var currSin = Mathf.Sin(currRad);
  97. var currCos = Mathf.Cos(currRad);
  98. var pos0 = new Vector3(serie.context.center.x + radius3 * currSin, serie.context.center.y + radius3 * currCos);
  99. if ((currAngle - startAngle) % 360 > 180)
  100. {
  101. currSin = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
  102. currCos = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
  103. }
  104. var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
  105. r4 += labelLine.lineLength1 + labelLine.lineWidth * 4;
  106. r4 += serieData.labelObject.text.GetPreferredWidth() / 2;
  107. serieData.context.labelPosition = pos0 + ((currAngle - startAngle) % 360 > 180 ? Vector3.left : Vector3.right) * r4;
  108. }
  109. else
  110. {
  111. labelRadius = serie.context.outsideRadius + (labelLine == null ? 0 : labelLine.lineLength1);
  112. labelCenter = new Vector2(serie.context.center.x + labelRadius * Mathf.Sin(currRad),
  113. serie.context.center.y + labelRadius * Mathf.Cos(currRad));
  114. serieData.context.labelPosition = labelCenter;
  115. }
  116. break;
  117. }
  118. }
  119. public static void AvoidLabelOverlap(Serie serie, ComponentTheme theme)
  120. {
  121. if (!serie.avoidLabelOverlap) return;
  122. var lastCheckPos = Vector3.zero;
  123. var lastX = 0f;
  124. var data = serie.data;
  125. var splitCount = 0;
  126. for (int n = 0; n < data.Count; n++)
  127. {
  128. var serieData = data[n];
  129. if (serieData.context.labelPosition.x != 0 && serieData.context.labelPosition.x < serie.context.center.x)
  130. {
  131. splitCount = n;
  132. break;
  133. }
  134. }
  135. for (int n = 0; n < splitCount; n++)
  136. {
  137. CheckSerieDataLabel(serie, data[n], splitCount, false, theme, ref lastCheckPos, ref lastX);
  138. }
  139. lastCheckPos = Vector3.zero;
  140. for (int n = data.Count - 1; n >= splitCount; n--)
  141. {
  142. CheckSerieDataLabel(serie, data[n], data.Count - splitCount, true, theme, ref lastCheckPos, ref lastX);
  143. }
  144. }
  145. private static void CheckSerieDataLabel(Serie serie, SerieData serieData, int total, bool isLeft, ComponentTheme theme,
  146. ref Vector3 lastCheckPos, ref float lastX)
  147. {
  148. if (!serieData.context.canShowLabel)
  149. {
  150. serieData.SetLabelActive(false);
  151. return;
  152. }
  153. if (!serieData.show) return;
  154. var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
  155. var isOutside = serieLabel.position == LabelStyle.Position.Outside ||
  156. serieLabel.position == LabelStyle.Position.Default;
  157. if (!serieLabel.show) return;
  158. if (!isOutside) return;
  159. var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
  160. var fontSize = serieData.labelObject.GetHeight();
  161. if (lastCheckPos == Vector3.zero)
  162. {
  163. lastCheckPos = serieData.context.labelPosition;
  164. }
  165. else if (serieData.context.labelPosition.x != 0)
  166. {
  167. if (lastCheckPos.y - serieData.context.labelPosition.y < fontSize)
  168. {
  169. var labelRadius = serie.context.outsideRadius + labelLine.lineLength1;
  170. var y1 = lastCheckPos.y - fontSize;
  171. var cy = serie.context.center.y;
  172. var diff = Mathf.Abs(y1 - cy);
  173. var diffX = labelRadius * labelRadius - diff * diff;
  174. diffX = diffX <= 0 ? 0 : diffX;
  175. var x1 = serie.context.center.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
  176. var newPos = new Vector3(x1, y1);
  177. serieData.context.labelPosition = newPos;
  178. var angle = ChartHelper.GetAngle360(Vector2.up, newPos - serie.context.center);
  179. if (angle >= 180 && angle <= 270)
  180. {
  181. serieData.context.labelPosition = new Vector3(isLeft?(++lastX): (--lastX), y1);
  182. }
  183. else if (angle < 180 && angle >= 90)
  184. {
  185. serieData.context.labelPosition = new Vector3(isLeft?(++lastX): (--lastX), y1);
  186. }
  187. else
  188. {
  189. lastX = x1;
  190. }
  191. }
  192. else
  193. {
  194. lastX = serieData.context.labelPosition.x;
  195. }
  196. lastCheckPos = serieData.context.labelPosition;
  197. serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serie, serieData, serieLabel, labelLine));
  198. }
  199. }
  200. public static Vector3 GetRealLabelPosition(Serie serie, SerieData serieData, LabelStyle label, LabelLine labelLine)
  201. {
  202. if (label == null || labelLine == null)
  203. return serieData.context.labelPosition;
  204. var isOutside = label.position == LabelStyle.Position.Outside ||
  205. label.position == LabelStyle.Position.Default;
  206. if (isOutside && labelLine.lineType != LabelLine.LineType.HorizontalLine)
  207. {
  208. var currAngle = serieData.context.halfAngle;
  209. var offset = labelLine.lineLength2 + serieData.labelObject.GetTextWidth() / 2;
  210. var angle = (currAngle - serie.context.startAngle) % 360;
  211. var isLeft = angle > 180 || (angle == 0 && serieData.context.startAngle > 0);
  212. if (isLeft)
  213. return serieData.context.labelPosition + new Vector3(-offset, 0, 0);
  214. else
  215. return serieData.context.labelPosition + new Vector3(offset, 0, 0);
  216. }
  217. else
  218. {
  219. return serieData.context.labelPosition;
  220. }
  221. }
  222. }
  223. }