71bc21577246949d80708a78c38c839b3a0d20ab918534298e4c26fcfeb279036d078b6bbe3fea9b33ea8f37395c770a510f5a912750b082abffe87c9d6963 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. import { doUpdate } from '../class/updater.class'
  2. import { radarAxisConfig } from '../config/index'
  3. import { deepClone, getCircleRadianPoint } from '@jiaminghi/c-render/lib/plugin/util'
  4. import { deepMerge, getPointToLineDistance } from '../util'
  5. export function radarAxis (chart, option = {}) {
  6. let { radar } = option
  7. let radarAxis = []
  8. if (radar) {
  9. radarAxis = mergeRadarAxisDefaultConfig(radar)
  10. radarAxis = calcRadarAxisCenter(radarAxis, chart)
  11. radarAxis = calcRadarAxisRingRadius(radarAxis, chart)
  12. radarAxis = calcRadarAxisLinePosition(radarAxis)
  13. radarAxis = calcRadarAxisAreaRadius(radarAxis)
  14. radarAxis = calcRadarAxisLabelPosition(radarAxis)
  15. radarAxis = [radarAxis]
  16. }
  17. let radarAxisForUpdate = radarAxis
  18. if (radarAxis.length && !radarAxis[0].show) radarAxisForUpdate = []
  19. doUpdate({
  20. chart,
  21. series: radarAxisForUpdate,
  22. key: 'radarAxisSplitArea',
  23. getGraphConfig: getSplitAreaConfig,
  24. beforeUpdate: beforeUpdateSplitArea,
  25. beforeChange: beforeChangeSplitArea
  26. })
  27. doUpdate({
  28. chart,
  29. series: radarAxisForUpdate,
  30. key: 'radarAxisSplitLine',
  31. getGraphConfig: getSplitLineConfig,
  32. beforeUpdate: beforeUpdateSplitLine,
  33. beforeChange: beforeChangeSplitLine
  34. })
  35. doUpdate({
  36. chart,
  37. series: radarAxisForUpdate,
  38. key: 'radarAxisLine',
  39. getGraphConfig: getAxisLineConfig,
  40. })
  41. doUpdate({
  42. chart,
  43. series: radarAxisForUpdate,
  44. key: 'radarAxisLable',
  45. getGraphConfig: getAxisLabelConfig,
  46. })
  47. chart.radarAxis = radarAxis[0]
  48. }
  49. function mergeRadarAxisDefaultConfig (radar) {
  50. return deepMerge(deepClone(radarAxisConfig), radar)
  51. }
  52. function calcRadarAxisCenter (radarAxis, chart) {
  53. const { area } = chart.render
  54. const { center } = radarAxis
  55. radarAxis.centerPos = center.map((v, i) => {
  56. if (typeof v === 'number') return v
  57. return parseInt(v) / 100 * area[i]
  58. })
  59. return radarAxis
  60. }
  61. function calcRadarAxisRingRadius (radarAxis, chart) {
  62. const { area } = chart.render
  63. let { splitNum, radius } = radarAxis
  64. const maxRadius = Math.min(...area) / 2
  65. if (typeof radius !== 'number') radius = parseInt(radius) / 100 * maxRadius
  66. const splitGap = radius / splitNum
  67. radarAxis.ringRadius = new Array(splitNum).fill(0)
  68. .map((foo, i) => splitGap * (i + 1))
  69. radarAxis.radius = radius
  70. return radarAxis
  71. }
  72. function calcRadarAxisLinePosition (radarAxis) {
  73. const { indicator, centerPos, radius, startAngle } = radarAxis
  74. const fullAngle = Math.PI * 2
  75. const indicatorNum = indicator.length
  76. const indicatorGap = fullAngle / indicatorNum
  77. const angles = new Array(indicatorNum).fill(0)
  78. .map((foo, i) => indicatorGap * i + startAngle)
  79. radarAxis.axisLineAngles = angles
  80. radarAxis.axisLinePosition = angles.map(g => {
  81. return getCircleRadianPoint(...centerPos, radius, g)
  82. })
  83. return radarAxis
  84. }
  85. function calcRadarAxisAreaRadius (radarAxis) {
  86. const { ringRadius } = radarAxis
  87. const subRadius = ringRadius[0] / 2
  88. radarAxis.areaRadius = ringRadius.map(r => r - subRadius)
  89. return radarAxis
  90. }
  91. function calcRadarAxisLabelPosition (radarAxis) {
  92. let { axisLineAngles, centerPos, radius, axisLabel } = radarAxis
  93. radius += axisLabel.labelGap
  94. radarAxis.axisLabelPosition = axisLineAngles.map(angle =>
  95. getCircleRadianPoint(...centerPos, radius, angle))
  96. return radarAxis
  97. }
  98. function getSplitAreaConfig (radarAxis) {
  99. const { areaRadius, polygon, animationCurve, animationFrame, rLevel } = radarAxis
  100. const name = polygon ? 'regPolygon' : 'ring'
  101. return areaRadius.map((foo, i) => ({
  102. name,
  103. index: rLevel,
  104. visible: radarAxis.splitArea.show,
  105. animationCurve,
  106. animationFrame,
  107. shape: getSplitAreaShape(radarAxis, i),
  108. style: getSplitAreaStyle(radarAxis, i)
  109. }))
  110. }
  111. function getSplitAreaShape (radarAxis, i) {
  112. const { polygon, areaRadius, indicator, centerPos } = radarAxis
  113. const indicatorNum = indicator.length
  114. let shape = {
  115. rx: centerPos[0],
  116. ry: centerPos[1],
  117. r: areaRadius[i]
  118. }
  119. if (polygon) shape.side = indicatorNum
  120. return shape
  121. }
  122. function getSplitAreaStyle (radarAxis, i) {
  123. const { splitArea, ringRadius, axisLineAngles, polygon, centerPos } = radarAxis
  124. let { color, style } = splitArea
  125. style = {
  126. fill: 'rgba(0, 0, 0, 0)',
  127. ...style
  128. }
  129. let lineWidth = ringRadius[0] - 0
  130. if (polygon) {
  131. const point1 = getCircleRadianPoint(...centerPos, ringRadius[0], axisLineAngles[0])
  132. const point2 = getCircleRadianPoint(...centerPos, ringRadius[0], axisLineAngles[1])
  133. lineWidth = getPointToLineDistance(centerPos, point1, point2)
  134. }
  135. style = deepMerge(deepClone(style, true), { lineWidth })
  136. if (!color.length) return style
  137. const colorNum = color.length
  138. return deepMerge(style, { stroke: color[i % colorNum] })
  139. }
  140. function beforeUpdateSplitArea (graphs, radarAxis, i, updater) {
  141. const cache = graphs[i]
  142. if (!cache) return
  143. const { render } = updater.chart
  144. const { polygon } = radarAxis
  145. const { name } = cache[0]
  146. const currentName = polygon ? 'regPolygon' : 'ring'
  147. const delAll = currentName !== name
  148. if (!delAll) return
  149. cache.forEach(g => render.delGraph(g))
  150. graphs[i] = null
  151. }
  152. function beforeChangeSplitArea (graph, config) {
  153. const side = config.shape.side
  154. if (typeof side !== 'number') return
  155. graph.shape.side = side
  156. }
  157. function getSplitLineConfig (radarAxis) {
  158. const { ringRadius, polygon, animationCurve, animationFrame, rLevel } = radarAxis
  159. const name = polygon ? 'regPolygon' : 'ring'
  160. return ringRadius.map((foo, i) => ({
  161. name,
  162. index: rLevel,
  163. animationCurve,
  164. animationFrame,
  165. visible: radarAxis.splitLine.show,
  166. shape: getSplitLineShape(radarAxis, i),
  167. style: getSplitLineStyle(radarAxis, i)
  168. }))
  169. }
  170. function getSplitLineShape (radarAxis, i) {
  171. const { ringRadius, centerPos, indicator, polygon } = radarAxis
  172. const shape = {
  173. rx: centerPos[0],
  174. ry: centerPos[1],
  175. r: ringRadius[i]
  176. }
  177. const indicatorNum = indicator.length
  178. if (polygon) shape.side = indicatorNum
  179. return shape
  180. }
  181. function getSplitLineStyle (radarAxis, i) {
  182. const { splitLine } = radarAxis
  183. let { color, style } = splitLine
  184. style = {
  185. fill: 'rgba(0, 0, 0, 0)',
  186. ...style
  187. }
  188. if (!color.length) return style
  189. const colorNum = color.length
  190. return deepMerge(style, { stroke: color[i % colorNum] })
  191. }
  192. function beforeUpdateSplitLine (graphs, radarAxis, i, updater) {
  193. const cache = graphs[i]
  194. if (!cache) return
  195. const { render } = updater.chart
  196. const { polygon } = radarAxis
  197. const { name } = cache[0]
  198. const currenName = polygon ? 'regPolygon' : 'ring'
  199. const delAll = currenName !== name
  200. if (!delAll) return
  201. cache.forEach(g => render.delGraph(g))
  202. graphs[i] = null
  203. }
  204. function beforeChangeSplitLine (graph, config) {
  205. const side = config.shape.side
  206. if (typeof side !== 'number') return
  207. graph.shape.side = side
  208. }
  209. function getAxisLineConfig (radarAxis) {
  210. const { axisLinePosition, animationCurve, animationFrame, rLevel } = radarAxis
  211. return axisLinePosition.map((foo, i) => ({
  212. name: 'polyline',
  213. index: rLevel,
  214. visible: radarAxis.axisLine.show,
  215. animationCurve,
  216. animationFrame,
  217. shape: getAxisLineShape(radarAxis, i),
  218. style: getAxisLineStyle(radarAxis, i)
  219. }))
  220. }
  221. function getAxisLineShape (radarAxis, i) {
  222. const { centerPos, axisLinePosition } = radarAxis
  223. const points = [centerPos, axisLinePosition[i]]
  224. return { points }
  225. }
  226. function getAxisLineStyle (radarAxis, i) {
  227. const { axisLine } = radarAxis
  228. const { color, style } = axisLine
  229. if (!color.length) return style
  230. const colorNum = color.length
  231. return deepMerge(style, { stroke: color[i % colorNum] })
  232. }
  233. function getAxisLabelConfig (radarAxis) {
  234. const { axisLabelPosition, animationCurve, animationFrame, rLevel } = radarAxis
  235. return axisLabelPosition.map((foo, i) => ({
  236. name: 'text',
  237. index: rLevel,
  238. visible: radarAxis.axisLabel.show,
  239. animationCurve,
  240. animationFrame,
  241. shape: getAxisLableShape(radarAxis, i),
  242. style: getAxisLableStyle(radarAxis, i)
  243. }))
  244. }
  245. function getAxisLableShape (radarAxis, i) {
  246. const { axisLabelPosition, indicator } = radarAxis
  247. return {
  248. content: indicator[i].name,
  249. position: axisLabelPosition[i]
  250. }
  251. }
  252. function getAxisLableStyle (radarAxis, i) {
  253. const { axisLabel, centerPos: [x, y], axisLabelPosition } = radarAxis
  254. let { color, style } = axisLabel
  255. const [labelXpos, labelYPos] = axisLabelPosition[i]
  256. const textAlign = labelXpos > x ? 'left' : 'right'
  257. const textBaseline = labelYPos > y ? 'top' : 'bottom'
  258. style = deepMerge({
  259. textAlign,
  260. textBaseline
  261. }, style)
  262. if (!color.length) return style
  263. const colorNum = color.length
  264. return deepMerge(style, { fill: color[i % colorNum] })
  265. }