雷达图参考 https://bizcharts.alibaba-inc.com/product/bizcharts/demo/130

image.png

  1. import React, { memo } from 'react';
  2. import PropTypes from 'prop-types'
  3. import {
  4. Chart,
  5. Geom,
  6. Axis,
  7. Tooltip,
  8. Coord,
  9. Legend,
  10. Guide,
  11. } from 'bizcharts';
  12. const { Html } = Guide
  13. const scale = {
  14. score: {
  15. min: 0,
  16. max: 100,
  17. },
  18. user: {
  19. formatter: val => {
  20. return ({ '1': '一季度', '2': '二季度', '3': '三季度', '4': '四季度' }[val])
  21. }
  22. },
  23. };
  24. RadarChart.propTypes = {
  25. dataSource: PropTypes.array.isRequired,
  26. onLegendItemClick: PropTypes.func.isRequired,
  27. quarter: PropTypes.number.isRequired,
  28. padding: PropTypes.array,
  29. height: PropTypes.number,
  30. }
  31. function RadarChart(props) {
  32. const {
  33. dataSource, onLegendItemClick, padding = [24, 24, 48, 24], height = 360, quarter
  34. } = props
  35. return (
  36. <Chart
  37. forceFit
  38. data={dataSource}
  39. height={height}
  40. padding={padding}
  41. scale={scale}
  42. filter={
  43. [['user', val => val === String(quarter)]]
  44. }
  45. onLegendItemClick={onLegendItemClick}
  46. >
  47. <Coord type="polar" radius={0.8} />
  48. <Tooltip />
  49. <Axis
  50. name="item"
  51. line={null}
  52. tickLine={null}
  53. grid={{
  54. lineStyle: {
  55. lineDash: null,
  56. },
  57. hideFirstLine: false,
  58. }}
  59. />
  60. <Axis
  61. name="score"
  62. line={null}
  63. tickLine={null}
  64. label={null}
  65. grid={{
  66. type: 'polygon',
  67. lineStyle: {
  68. lineDash: null,
  69. },
  70. alternateColor: 'rgba(0, 0, 0, 0.04)',
  71. }}
  72. />
  73. <Legend
  74. name="user"
  75. marker="circle"
  76. offset={30}
  77. selectedMode="single"
  78. />
  79. <Guide>
  80. <Html
  81. position={['50%', '50%']}
  82. html={(_, score) => {
  83. const { values } = score.score || []
  84. return nodeString(values)
  85. }}
  86. alignX="middle"
  87. alignY="middle"
  88. />
  89. </Guide>
  90. <Geom type="line" position="item*score" color="user" size={2} />
  91. <Geom
  92. type="point"
  93. position="item*score"
  94. color="user"
  95. shape="circle"
  96. size={4}
  97. style={{
  98. stroke: '#fff',
  99. lineWidth: 1,
  100. fillOpacity: 1,
  101. }}
  102. />
  103. </Chart>
  104. );
  105. }
  106. export default memo(RadarChart)
  107. // Guide.Html
  108. function nodeString(values) {
  109. let avg = values.reduce((prev, next) => prev + next, 0) / values.length;
  110. avg = Math.round(avg * 100 / 100)
  111. return `<div style=color:#8c8c8c;text-align: center;width: 10em;><b style=color:#262626;font-size:24px>${avg}</b></div>`
  112. }

radar数据格式

  1. export const radarData = [
  2. { 'item': 'UI设计', 'user': '1', 'score': 0, key: 'UI' },
  3. { 'item': 'UI设计', 'user': '2', 'score': 0, key: 'UI' },
  4. { 'item': 'UI设计', 'user': '3', 'score': 0, key: 'UI' },
  5. { 'item': 'UI设计', 'user': '4', 'score': 0, key: 'UI' },
  6. { 'item': 'WEB', 'user': '1', 'score': 0, key: 'WEB' },
  7. { 'item': 'WEB', 'user': '2', 'score': 0, key: 'WEB' },
  8. { 'item': 'WEB', 'user': '3', 'score': 0, key: 'WEB' },
  9. { 'item': 'WEB', 'user': '4', 'score': 0, key: 'WEB' },
  10. { 'item': 'FRONT', 'user': '1', 'score': 0, key: 'FRONT' },
  11. { 'item': 'FRONT', 'user': '2', 'score': 0, key: 'FRONT' },
  12. { 'item': 'FRONT', 'user': '3', 'score': 0, key: 'FRONT' },
  13. { 'item': 'FRONT', 'user': '4', 'score': 0, key: 'FRONT' },
  14. { 'item': 'MYSQL', 'user': '1', 'score': 0, key: 'MYSQL' },
  15. { 'item': 'MYSQL', 'user': '2', 'score': 0, key: 'MYSQL' },
  16. { 'item': 'MYSQL', 'user': '3', 'score': 0, key: 'MYSQL' },
  17. { 'item': 'MYSQL', 'user': '4', 'score': 0, key: 'MYSQL' },
  18. { 'item': 'NGINX', 'user': '1', 'score': 0, key: 'NGINX' },
  19. { 'item': 'NGINX', 'user': '2', 'score': 0, key: 'NGINX' },
  20. { 'item': 'NGINX', 'user': '3', 'score': 0, key: 'NGINX' },
  21. { 'item': 'NGINX', 'user': '4', 'score': 0, key: 'NGINX' },
  22. ];