24af3159b3a4f44ae0f5fc789866e766c69e898d8f0f097b8ad1759f56370b6c1154deb466c735858806613c89355a9b1bd37b5548d5821c6bf2599d8f5c86 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import { doUpdate } from '../class/updater.class'
  2. import { radarConfig } from '../config/index'
  3. import { getCircleRadianPoint } from '@jiaminghi/c-render/lib/plugin/util'
  4. import { getColorFromRgbValue, getRgbaValue } from '@jiaminghi/color'
  5. import { deepMerge, initNeedSeries } from '../util'
  6. export function radar (chart, option = {}) {
  7. let { series } = option
  8. if (!series) series = []
  9. let radars = initNeedSeries(series, radarConfig, 'radar')
  10. radars = calcRadarPosition(radars, chart)
  11. radars = calcRadarLabelPosition(radars, chart)
  12. radars = calcRadarLabelAlign(radars, chart)
  13. doUpdate({
  14. chart,
  15. series: radars,
  16. key: 'radar',
  17. getGraphConfig: getRadarConfig,
  18. getStartGraphConfig: getStartRadarConfig,
  19. beforeChange: beforeChangeRadar
  20. })
  21. doUpdate({
  22. chart,
  23. series: radars,
  24. key: 'radarPoint',
  25. getGraphConfig: getPointConfig,
  26. getStartGraphConfig: getStartPointConfig,
  27. })
  28. doUpdate({
  29. chart,
  30. series: radars,
  31. key: 'radarLabel',
  32. getGraphConfig: getLabelConfig
  33. })
  34. }
  35. function calcRadarPosition (radars, chart) {
  36. const { radarAxis } = chart
  37. if (!radarAxis) return []
  38. const { indicator, axisLineAngles, radius, centerPos } = radarAxis
  39. radars.forEach(radarItem => {
  40. const { data } = radarItem
  41. radarItem.dataRadius = []
  42. radarItem.radarPosition = indicator.map(({ max, min }, i) => {
  43. let v = data[i]
  44. if (typeof max !== 'number') max = v
  45. if (typeof min !== 'number') min = 0
  46. if (typeof v !== 'number') v = min
  47. const dataRadius = (v - min) / (max - min) * radius
  48. radarItem.dataRadius[i] = dataRadius
  49. return getCircleRadianPoint(...centerPos, dataRadius, axisLineAngles[i])
  50. })
  51. })
  52. return radars
  53. }
  54. function calcRadarLabelPosition (radars, chart) {
  55. const { radarAxis } = chart
  56. if (!radarAxis) return []
  57. const { centerPos, axisLineAngles } = radarAxis
  58. radars.forEach(radarItem => {
  59. const { dataRadius, label } = radarItem
  60. const { labelGap } = label
  61. radarItem.labelPosition = dataRadius.map((r, i) => {
  62. return getCircleRadianPoint(...centerPos, r + labelGap, axisLineAngles[i])
  63. })
  64. })
  65. return radars
  66. }
  67. function calcRadarLabelAlign (radars, chart) {
  68. const { radarAxis } = chart
  69. if (!radarAxis) return []
  70. const { centerPos: [x, y] } = radarAxis
  71. radars.forEach(radarItem => {
  72. const { labelPosition } = radarItem
  73. const labelAlign = labelPosition.map(([lx, ly]) => {
  74. const textAlign = lx > x ? 'left' : 'right'
  75. const textBaseline = ly > y ? 'top' : 'bottom'
  76. return {
  77. textAlign,
  78. textBaseline
  79. }
  80. })
  81. radarItem.labelAlign = labelAlign
  82. })
  83. return radars
  84. }
  85. function getRadarConfig (radarItem) {
  86. const { animationCurve, animationFrame, rLevel } = radarItem
  87. return [{
  88. name: 'polyline',
  89. index: rLevel,
  90. animationCurve,
  91. animationFrame,
  92. shape: getRadarShape(radarItem),
  93. style: getRadarStyle(radarItem)
  94. }]
  95. }
  96. function getStartRadarConfig (radarItem, updater) {
  97. const { radarAxis: { centerPos } } = updater.chart
  98. const config = getRadarConfig(radarItem)[0]
  99. const pointNum = config.shape.points.length
  100. const points = new Array(pointNum).fill(0).map(foo => [...centerPos])
  101. config.shape.points = points
  102. return [config]
  103. }
  104. function getRadarShape (radarItem) {
  105. const { radarPosition } = radarItem
  106. return {
  107. points: radarPosition,
  108. close: true
  109. }
  110. }
  111. function getRadarStyle(radarItem) {
  112. const { radarStyle, color } = radarItem
  113. const colorRgbaValue = getRgbaValue(color)
  114. colorRgbaValue[3] = 0.5
  115. const radarDefaultColor = {
  116. stroke: color,
  117. fill: getColorFromRgbValue(colorRgbaValue)
  118. }
  119. return deepMerge(radarDefaultColor, radarStyle)
  120. }
  121. function beforeChangeRadar (graph, { shape }) {
  122. const graphPoints = graph.shape.points
  123. const graphPointsNum = graphPoints.length
  124. const pointsNum = shape.points.length
  125. if (pointsNum > graphPointsNum) {
  126. const lastPoint = graphPoints.slice(-1)[0]
  127. const newAddPoints = new Array(pointsNum - graphPointsNum)
  128. .fill(0).map(foo => ([...lastPoint]))
  129. graphPoints.push(...newAddPoints)
  130. } else if (pointsNum < graphPointsNum) {
  131. graphPoints.splice(pointsNum)
  132. }
  133. }
  134. function getPointConfig (radarItem) {
  135. const { radarPosition, animationCurve, animationFrame, rLevel } = radarItem
  136. return radarPosition.map((foo, i) => ({
  137. name: 'circle',
  138. index: rLevel,
  139. animationCurve,
  140. animationFrame,
  141. visible: radarItem.point.show,
  142. shape: getPointShape(radarItem, i),
  143. style: getPointStyle(radarItem, i),
  144. }))
  145. }
  146. function getStartPointConfig (radarItem) {
  147. const configs = getPointConfig(radarItem)
  148. configs.forEach(config => config.shape.r = 0.01)
  149. return configs
  150. }
  151. function getPointShape (radarItem, i) {
  152. const { radarPosition, point } = radarItem
  153. const { radius } = point
  154. const position = radarPosition[i]
  155. return {
  156. rx: position[0],
  157. ry: position[1],
  158. r: radius
  159. }
  160. }
  161. function getPointStyle (radarItem, i) {
  162. const { point, color } = radarItem
  163. const { style } = point
  164. return deepMerge({ stroke: color }, style)
  165. }
  166. function getLabelConfig (radarItem) {
  167. const { labelPosition, animationCurve, animationFrame, rLevel } = radarItem
  168. return labelPosition.map((foo, i) => ({
  169. name: 'text',
  170. index: rLevel,
  171. visible: radarItem.label.show,
  172. animationCurve,
  173. animationFrame,
  174. shape: getLabelShape(radarItem, i),
  175. style: getLabelStyle(radarItem, i)
  176. }))
  177. }
  178. function getLabelShape (radarItem, i) {
  179. const { labelPosition, label, data } = radarItem
  180. const { offset, formatter } = label
  181. const position = mergePointOffset(labelPosition[i], offset)
  182. let labelText = data[i] ? data[i].toString() : '0'
  183. const formatterType = typeof formatter
  184. if (formatterType === 'string') labelText = formatter.replace('{value}', labelText)
  185. if (formatterType === 'function') labelText = formatter(labelText)
  186. return {
  187. content: labelText,
  188. position
  189. }
  190. }
  191. function mergePointOffset ([x, y], [ox, oy]) {
  192. return [x + ox, y + oy]
  193. }
  194. function getLabelStyle (radarItem, i) {
  195. const { label, color, labelAlign } = radarItem
  196. const { style } = label
  197. const defaultColorAndAlign = {
  198. fill: color,
  199. ...labelAlign[i]
  200. }
  201. return deepMerge(defaultColorAndAlign, style)
  202. }