如何在React中用reactchartjs-2和chart.js绘制带圆角的环形图
Got it, let's tackle this rounded doughnut chart using react-chartjs-2 and Chart.js in React. Here's a step-by-step solution that gets you the exact rounded edge effect you're aiming for:
1. Install Required Dependencies
First, make sure you have the necessary packages installed. Run this command in your project directory:
npm install chart.js react-chartjs-2 # Or if you use yarn yarn add chart.js react-chartjs-2
2. Create a Custom Rounded Doughnut Component
The key here is a custom Chart.js plugin that modifies the arc paths to add rounded edges. Let's build the component:
import React from 'react'; import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'; import { Doughnut } from 'react-chartjs-2'; // Register required Chart.js elements ChartJS.register(ArcElement, Tooltip, Legend); // Custom plugin to add rounded edges to doughnut arcs const roundedDoughnutPlugin = { beforeDraw: (chart) => { if (chart.config.type !== 'doughnut') return; const ctx = chart.ctx; const chartArea = chart.chartArea; chart.data.datasets.forEach((dataset, datasetIndex) => { const meta = chart.getDatasetMeta(datasetIndex); meta.data.forEach((arc, index) => { const model = arc._model; const arcStart = model.startAngle; const arcEnd = model.endAngle; const arcSweep = arcEnd - arcStart; const innerRadius = model.innerRadius; const outerRadius = model.outerRadius; const cornerRadius = 10; // Adjust this value to control roundness // Only add rounded corners if the arc is large enough to avoid glitches if (arcSweep > 0.1) { // Calculate start/end coordinates for outer and inner arcs const startX = chartArea.left + Math.cos(arcStart) * outerRadius; const startY = chartArea.top + Math.sin(arcStart) * outerRadius; const endX = chartArea.left + Math.cos(arcEnd) * outerRadius; const endY = chartArea.top + Math.sin(arcEnd) * outerRadius; const innerStartX = chartArea.left + Math.cos(arcStart) * innerRadius; const innerStartY = chartArea.top + Math.sin(arcStart) * innerRadius; const innerEndX = chartArea.left + Math.cos(arcEnd) * innerRadius; const innerEndY = chartArea.top + Math.sin(arcEnd) * innerRadius; ctx.save(); ctx.beginPath(); // Draw rounded start corner + outer arc ctx.arc(startX, startY, cornerRadius, arcStart + Math.PI / 2, arcStart - Math.PI / 2, true); ctx.arc(chartArea.left, chartArea.top, outerRadius, arcStart, arcEnd); // Draw rounded end corner + inner arc (reverse direction) ctx.arc(endX, endY, cornerRadius, arcEnd - Math.PI / 2, arcEnd + Math.PI / 2, true); ctx.arc(chartArea.left, chartArea.top, innerRadius, arcEnd, arcStart, true); ctx.closePath(); ctx.fillStyle = model.backgroundColor; ctx.fill(); ctx.restore(); // Hide the original sharp-edged arc arc._model.skip = true; } }); }); }, }; const RoundedDoughnutChart = () => { const data = { labels: ['Red', 'Blue', 'Yellow'], datasets: [ { label: '# of Votes', data: [12, 19, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.7)', 'rgba(54, 162, 235, 0.7)', 'rgba(255, 206, 86, 0.7)', ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', ], borderWidth: 0, // Remove default border since we're drawing custom arcs }, ], }; const options = { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom', }, tooltip: { callbacks: { label: (context) => `${context.label}: ${context.parsed}`, }, }, }, cutout: '70%', // Adjust inner hole size (0-100% of chart radius) }; return ( <div style={{ height: '400px', width: '400px' }}> <Doughnut data={data} options={options} plugins={[roundedDoughnutPlugin]} /> </div> ); }; export default RoundedDoughnutChart;
3. Key Customizations to Tweak
- Corner Roundness: Change the
cornerRadiusvalue in the plugin to make edges more/less rounded (higher = rounder). - Inner Hole Size: Adjust the
cutoutvalue inoptionsto resize the doughnut's inner gap. - Color Scheme: Update
backgroundColorandborderColorin the dataset to match your design. - Chart Dimensions: Modify the wrapping div's inline styles to control the chart's size.
4. Use the Component in Your App
Import and drop the component wherever you need it:
import RoundedDoughnutChart from './RoundedDoughnutChart'; function App() { return ( <div className="App"> <h1>Rounded Doughnut Chart Demo</h1> <RoundedDoughnutChart /> </div> ); } export default App;
This solution works by intercepting the chart's draw cycle, drawing custom rounded arcs instead of the default sharp ones, and skipping the original arc rendering. The plugin checks arc size to avoid visual glitches with small segments.
内容的提问来源于stack exchange,提问作者Ashish Prajapathi

