You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中用reactchartjs-2和chart.js绘制带圆角的环形图

Create a Rounded Doughnut Chart in React with react-chartjs-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 cornerRadius value in the plugin to make edges more/less rounded (higher = rounder).
  • Inner Hole Size: Adjust the cutout value in options to resize the doughnut's inner gap.
  • Color Scheme: Update backgroundColor and borderColor in 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:00:51