index.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * @Author: code4eat awesomedema@gmail.com
  3. * @Date: 2024-07-09 14:53:59
  4. * @LastEditors: code4eat awesomedema@gmail.com
  5. * @LastEditTime: 2024-08-29 17:41:09
  6. * @FilePath: /MediScreen/src/components/singleBarChartComponent/index.tsx
  7. * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  8. */
  9. import React, { useRef, useEffect } from 'react';
  10. interface BarChartProps {
  11. data: { name: string; value: number }[];
  12. }
  13. const SingleBarChartComponent: React.FC<BarChartProps> = ({ data }) => {
  14. const canvasRef = useRef<HTMLCanvasElement>(null);
  15. useEffect(() => {
  16. const canvas = canvasRef.current;
  17. if (canvas) {
  18. const ctx = canvas.getContext('2d');
  19. if (!ctx) return;
  20. const resizeCanvas = () => {
  21. const parent = canvas.parentElement;
  22. if (parent) {
  23. const ratio = window.devicePixelRatio || 1;
  24. canvas.width = parent.clientWidth * ratio;
  25. canvas.height = parent.clientHeight * ratio;
  26. ctx.scale(ratio, ratio);
  27. canvas.style.width = `${parent.clientWidth}px`;
  28. canvas.style.height = `${parent.clientHeight}px`;
  29. }
  30. drawChart(); // 在调整大小后重新绘制图表
  31. };
  32. const drawChart = () => {
  33. const width = canvas.width / (window.devicePixelRatio || 1);
  34. const height = canvas.height / (window.devicePixelRatio || 1);
  35. const paddingX = 0;
  36. const paddingY = 15;
  37. const barWidth = (width - paddingX * 2) / (data.length * 2);
  38. const maxBarHeight = height - paddingY * 2;
  39. const maxValue = Math.max(...data.map((item) => item.value));
  40. ctx.clearRect(0, 0, width * (window.devicePixelRatio || 1), height * (window.devicePixelRatio || 1));
  41. const baseFontSize = Math.min(width, height) / 25;
  42. ctx.font = `${baseFontSize}px Arial`;
  43. ctx.strokeStyle = '#ccc';
  44. ctx.lineWidth = 0.5;
  45. ctx.globalAlpha = 0.2;
  46. const numLines = 5;
  47. for (let i = 0; i <= numLines; i++) {
  48. const y = paddingY + (i * maxBarHeight) / numLines;
  49. ctx.beginPath();
  50. ctx.moveTo(paddingX, y);
  51. ctx.lineTo(width - paddingX, y);
  52. ctx.stroke();
  53. }
  54. ctx.globalAlpha = 1.0;
  55. data.forEach((item, index) => {
  56. const barHeight = (item.value / maxValue) * maxBarHeight;
  57. const x = paddingX + index * barWidth * 2 + barWidth / 2;
  58. const y = height - paddingY - barHeight;
  59. const gradient = ctx.createLinearGradient(x, y, x, y + barHeight);
  60. gradient.addColorStop(0, 'rgba(128, 234, 255, 1)');
  61. gradient.addColorStop(1, 'rgba(128, 234, 255, 0)');
  62. ctx.fillStyle = gradient;
  63. ctx.fillRect(x, y, barWidth - 10, barHeight);
  64. ctx.fillStyle = gradient;
  65. ctx.beginPath();
  66. ctx.moveTo(x, y + barHeight);
  67. ctx.arcTo(x, y, x + barWidth - 10, y, 4);
  68. ctx.arcTo(x + barWidth - 10, y, x + barWidth - 10, y + barHeight, 4);
  69. ctx.arcTo(x + barWidth - 10, y + barHeight, x, y + barHeight, 4);
  70. ctx.arcTo(x, y + barHeight, x, y, 4);
  71. ctx.fill();
  72. ctx.fillStyle = '#ffffff';
  73. ctx.textAlign = 'center';
  74. ctx.fillText(item.value.toString(), x + (barWidth - 10) / 2, y - 10);
  75. ctx.fillText(item.name, x + (barWidth - 10) / 2, height - paddingY + baseFontSize * 1.5);
  76. });
  77. };
  78. resizeCanvas();
  79. window.addEventListener('resize', resizeCanvas);
  80. return () => {
  81. window.removeEventListener('resize', resizeCanvas);
  82. };
  83. }
  84. }, [data]);
  85. return <canvas ref={canvasRef} style={{ width: '100%', height: '100%' }} />;
  86. };
  87. export default SingleBarChartComponent;