123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- * @Author: code4eat awesomedema@gmail.com
- * @Date: 2024-07-09 14:53:59
- * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2024-08-29 17:41:09
- * @FilePath: /MediScreen/src/components/singleBarChartComponent/index.tsx
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
- */
- import React, { useRef, useEffect } from 'react';
- interface BarChartProps {
- data: { name: string; value: number }[];
- }
- const SingleBarChartComponent: React.FC<BarChartProps> = ({ data }) => {
- const canvasRef = useRef<HTMLCanvasElement>(null);
- useEffect(() => {
- const canvas = canvasRef.current;
- if (canvas) {
- const ctx = canvas.getContext('2d');
- if (!ctx) return;
- const resizeCanvas = () => {
- const parent = canvas.parentElement;
- if (parent) {
- const ratio = window.devicePixelRatio || 1;
- canvas.width = parent.clientWidth * ratio;
- canvas.height = parent.clientHeight * ratio;
- ctx.scale(ratio, ratio);
- canvas.style.width = `${parent.clientWidth}px`;
- canvas.style.height = `${parent.clientHeight}px`;
- }
- drawChart(); // 在调整大小后重新绘制图表
- };
- const drawChart = () => {
- const width = canvas.width / (window.devicePixelRatio || 1);
- const height = canvas.height / (window.devicePixelRatio || 1);
- const paddingX = 0;
- const paddingY = 15;
- const barWidth = (width - paddingX * 2) / (data.length * 2);
- const maxBarHeight = height - paddingY * 2;
- const maxValue = Math.max(...data.map((item) => item.value));
- ctx.clearRect(0, 0, width * (window.devicePixelRatio || 1), height * (window.devicePixelRatio || 1));
- const baseFontSize = Math.min(width, height) / 25;
- ctx.font = `${baseFontSize}px Arial`;
- ctx.strokeStyle = '#ccc';
- ctx.lineWidth = 0.5;
- ctx.globalAlpha = 0.2;
- const numLines = 5;
- for (let i = 0; i <= numLines; i++) {
- const y = paddingY + (i * maxBarHeight) / numLines;
- ctx.beginPath();
- ctx.moveTo(paddingX, y);
- ctx.lineTo(width - paddingX, y);
- ctx.stroke();
- }
- ctx.globalAlpha = 1.0;
- data.forEach((item, index) => {
- const barHeight = (item.value / maxValue) * maxBarHeight;
- const x = paddingX + index * barWidth * 2 + barWidth / 2;
- const y = height - paddingY - barHeight;
- const gradient = ctx.createLinearGradient(x, y, x, y + barHeight);
- gradient.addColorStop(0, 'rgba(128, 234, 255, 1)');
- gradient.addColorStop(1, 'rgba(128, 234, 255, 0)');
- ctx.fillStyle = gradient;
- ctx.fillRect(x, y, barWidth - 10, barHeight);
- ctx.fillStyle = gradient;
- ctx.beginPath();
- ctx.moveTo(x, y + barHeight);
- ctx.arcTo(x, y, x + barWidth - 10, y, 4);
- ctx.arcTo(x + barWidth - 10, y, x + barWidth - 10, y + barHeight, 4);
- ctx.arcTo(x + barWidth - 10, y + barHeight, x, y + barHeight, 4);
- ctx.arcTo(x, y + barHeight, x, y, 4);
- ctx.fill();
- ctx.fillStyle = '#ffffff';
- ctx.textAlign = 'center';
- ctx.fillText(item.value.toString(), x + (barWidth - 10) / 2, y - 10);
- ctx.fillText(item.name, x + (barWidth - 10) / 2, height - paddingY + baseFontSize * 1.5);
- });
- };
- resizeCanvas();
- window.addEventListener('resize', resizeCanvas);
- return () => {
- window.removeEventListener('resize', resizeCanvas);
- };
- }
- }, [data]);
- return <canvas ref={canvasRef} style={{ width: '100%', height: '100%' }} />;
- };
- export default SingleBarChartComponent;
|