LineChartSmall.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import * as d3 from 'd3';
  2. import {
  3. CHART_WIDTH,
  4. HEALTHY_STATUS_COLORS,
  5. LINE_CHART_LARGE_HEIGHT,
  6. LINE_CHART_SMALL_HEIGHT,
  7. LINE_COLOR,
  8. LINE_LABEL_FONT_SIZE,
  9. LINE_LABEL_Y_PADDING,
  10. LINE_SMALL_LABEL_FONT_SIZE,
  11. LINE_WIDTH,
  12. } from './consts';
  13. import { EHealthyStatus } from './Types';
  14. const LineChartSmall = ({
  15. data,
  16. format = d => d,
  17. unit = '',
  18. threshold,
  19. }: {
  20. data: number[];
  21. format?: (d: any) => string;
  22. unit?: string;
  23. threshold: number;
  24. }) => {
  25. const length = data.length;
  26. const width = CHART_WIDTH;
  27. const height = LINE_CHART_SMALL_HEIGHT - 3;
  28. const fontSize = LINE_SMALL_LABEL_FONT_SIZE;
  29. const xDomain = [0, length];
  30. const xRange = [0, CHART_WIDTH];
  31. let maxData = d3.max(data, d => d) as number;
  32. maxData = maxData === 0 ? 1 : maxData;
  33. const yDomain = [0, maxData * 1.1];
  34. const yRange = [height, 0];
  35. const xScale = d3.scaleLinear(xDomain, xRange);
  36. const yScale = d3.scaleLinear(yDomain, yRange);
  37. const nodes = data
  38. .map((d, i) => (d >= 0 ? [xScale(i + 0.5), yScale(d)] : undefined))
  39. .filter(a => a) as [number, number][];
  40. const line = d3
  41. .line()
  42. .curve(d3.curveBumpX)
  43. .x(d => d[0])
  44. .y(d => d[1]);
  45. return (
  46. <svg
  47. width={width}
  48. height={height}
  49. style={{ overflow: 'visible' }}
  50. fontSize={fontSize}
  51. fontWeight={500}
  52. >
  53. <g className="x-axis">
  54. <line x1={0} y1={height} x2={width} y2={height} stroke="#666" />
  55. <line
  56. x1={width - LINE_LABEL_Y_PADDING}
  57. y1={yScale(maxData)}
  58. x2={width}
  59. y2={yScale(maxData)}
  60. stroke="#666"
  61. strokeWidth="2"
  62. />
  63. </g>
  64. <g className="y-axis">
  65. <text
  66. x={width + LINE_LABEL_Y_PADDING}
  67. y={height}
  68. textAnchor="start"
  69. fill="#555"
  70. >
  71. {0}
  72. </text>
  73. <text
  74. x={width + LINE_LABEL_Y_PADDING}
  75. y={yScale(maxData) + 3}
  76. textAnchor="start"
  77. fill="#555"
  78. >
  79. {format(maxData)}
  80. </text>
  81. {unit && (
  82. <text
  83. x={width + LINE_LABEL_Y_PADDING}
  84. y={yScale(maxData) + 3 + fontSize}
  85. textAnchor="start"
  86. fontSize={fontSize - 2}
  87. fill="#555"
  88. >
  89. ({unit})
  90. </text>
  91. )}
  92. </g>
  93. <g className="line">
  94. {maxData >= threshold && (
  95. <line
  96. x1={xScale(0.5)}
  97. y1={yScale(threshold)}
  98. x2={xScale(data.length - 0.5)}
  99. y2={yScale(threshold)}
  100. stroke={HEALTHY_STATUS_COLORS[EHealthyStatus.warning]}
  101. strokeWidth={LINE_WIDTH + 1}
  102. strokeLinecap="round"
  103. strokeDasharray={"6 8"}
  104. />
  105. )}
  106. <path
  107. d={line(nodes) as any}
  108. fill="none"
  109. stroke={LINE_COLOR}
  110. strokeWidth={LINE_WIDTH}
  111. opacity={0.8}
  112. strokeLinecap="round"
  113. />
  114. </g>
  115. </svg>
  116. );
  117. };
  118. export default LineChartSmall;