如何用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




