You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Chart.js制作预填充环形图?求替代SVG的实现方案

Absolutely, you can build that pre-filled donut chart with Chart.js—even without relying on SVG-specific features. Here are a few practical, easy-to-implement approaches:

1. Stack Two Doughnut Charts (Simplest Solution)

The idea is to layer a background doughnut (for your pre-filled color) underneath your actual data doughnut. Just make sure their dimensions match perfectly so they line up.

const ctx = document.getElementById('preFilledDonut').getContext('2d');

// Background pre-filled ring
new Chart(ctx, {
  type: 'doughnut',
  data: {
    datasets: [{
      data: [100], // Fills the entire ring
      backgroundColor: '#f0f0f0', // Your pre-fill color
      borderWidth: 0,
      hoverOffset: 0
    }]
  },
  options: {
    cutout: '70%', // Match this with the data chart below
    responsive: true,
    maintainAspectRatio: false,
    plugins: {
      legend: { display: false },
      tooltip: { enabled: false } // Disable tooltips for the background
    }
  }
});

// Top data ring
new Chart(ctx, {
  type: 'doughnut',
  data: {
    datasets: [{
      data: [65, 35], // Your actual data + transparent filler
      backgroundColor: ['#2563eb', 'transparent'], // Transparent hides the unused portion
      borderWidth: 0,
      hoverOffset: 0
    }]
  },
  options: {
    cutout: '70%',
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { display: false } }
  }
});

Pros: No extra plugins needed, super easy to tweak colors and ring thickness. Just double-check the cutout value is identical for both charts.

2. Custom Drawing with Chart.js Plugin Hooks

If you prefer a single chart instance, use the beforeDraw hook to manually render the pre-filled ring before your data is drawn. This gives you more fine-grained control.

const ctx = document.getElementById('preFilledDonut').getContext('2d');

new Chart(ctx, {
  type: 'doughnut',
  data: {
    datasets: [{
      data: [65], // Your target data value
      backgroundColor: '#2563eb',
      borderWidth: 0
    }]
  },
  options: {
    cutout: '70%',
    responsive: true,
    maintainAspectRatio: false,
    plugins: {
      legend: { display: false },
      // Custom config for the pre-fill background
      preFill: {
        color: '#f0f0f0'
      }
    }
  },
  plugins: [{
    id: 'preFillBackground',
    beforeDraw: (chart) => {
      const { ctx, chartArea: { width, height }, options } = chart;
      const centerX = width / 2;
      const centerY = height / 2;
      const outerRadius = Math.min(width, height) / 2;
      const innerRadius = outerRadius * (options.cutout / 100);

      // Draw the pre-filled ring
      ctx.save();
      ctx.beginPath();
      ctx.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI);
      ctx.arc(centerX, centerY, innerRadius, 2 * Math.PI, 0, true);
      ctx.fillStyle = options.plugins.preFill.color;
      ctx.fill();
      ctx.restore();
    }
  }]
});

Pros: Clean single-instance setup, easy to add custom effects like gradients or partial pre-fills by adjusting the arc angles.

3. Filler Data for "Remaining" Pre-Fill

If your pre-fill is just the unused portion of the ring, you can skip layering entirely by adding a filler data point with your pre-fill color:

const ctx = document.getElementById('preFilledDonut').getContext('2d');

new Chart(ctx, {
  type: 'doughnut',
  data: {
    datasets: [{
      data: [65, 35], // Your data + remaining percentage
      backgroundColor: ['#2563eb', '#f0f0f0'], // Data color + pre-fill color
      borderWidth: 0
    }]
  },
  options: {
    cutout: '70%',
    plugins: { legend: { display: false } }
  }
});

Pros: The most straightforward option if your pre-fill represents the "empty" part of the ring. Perfect for simple progress-style donuts.

Pick the approach that best fits your specific pre-fill needs—all of these work without relying on SVG-specific features!

内容的提问来源于stack exchange,提问作者Abdullah Al Mamun

火山引擎 最新活动