C3环形图(Donut Chart)如何实现带连线的外部自定义标签?
Absolutely! I’ve tackled this exact requirement with C3.js before, so let me walk you through a reliable way to add external labels with connecting lines to your donut chart. Since C3 is built on top of D3.js, we can leverage D3’s drawing capabilities within C3’s lifecycle hooks to customize the labels.
Step 1: Base Donut Chart Configuration
First, set up your basic donut chart and disable the default internal labels (we’ll replace them with our custom ones):
<div id="chart"></div>
var chart = c3.generate({ bindto: '#chart', data: { columns: [ ['Data 1', 30], ['Data 2', 120], ['Data 3', 80] ], type: 'donut' }, donut: { label: { show: false // Turn off default internal labels }, width: 60 // Adjust donut width to make space for external labels }, onrendered: function() { // We'll add our custom label logic here } });
Step 2: Add Custom Labels & Lines in onrendered
Use C3’s onrendered callback to draw the labels and connecting lines after the chart renders. We’ll use D3 (which comes bundled with C3) to handle the SVG drawing:
onrendered: function() { var svg = d3.select('#chart svg'); // Clean up old custom elements to avoid duplicates on re-render svg.selectAll('.custom-donut-label, .custom-donut-line').remove(); // Target each donut arc var arcs = svg.selectAll('.c3-arc'); arcs.each(function(d) { // Get the center point (centroid) of the arc var centroid = d3.arc().centroid(d); // Calculate label position (adjust the 1.5 multiplier to move labels closer/farther) var labelX = centroid[0] * 1.5; var labelY = centroid[1] * 1.5; // Draw the connecting line from arc centroid to label svg.append('line') .attr('class', 'custom-donut-line') .attr('x1', centroid[0]) .attr('y1', centroid[1]) .attr('x2', labelX) .attr('y2', labelY) .attr('stroke', '#666') .attr('stroke-width', 1); // Draw the label text svg.append('text') .attr('class', 'custom-donut-label') // Adjust text position based on which side of the chart it's on .attr('x', labelX + (labelX > 0 ? 10 : -10)) .attr('y', labelY) .attr('text-anchor', labelX > 0 ? 'start' : 'end') .attr('fill', '#333') .style('font-size', '14px') .text(`${d.data.name}: ${d.data.value}`); }); }
Key Details to Customize
- Label Position: Adjust the
1.5multiplier inlabelX/labelYto move labels closer to or farther from the donut. - Line Style: Modify
strokeandstroke-widthto match your design system. - Text Style: Tweak
font-size,fill, and other CSS properties in thetextelement to fit your needs. - Avoid Duplicates: The cleanup step (
svg.selectAll(...)) ensures that when the chart re-renders (e.g., on data updates), old labels/lines are removed before drawing new ones.
Final Notes
This approach works entirely with C3 and its bundled D3 dependency—no extra libraries needed. It’s flexible enough to adapt to different chart sizes and label content, and it maintains the interactive behavior of your C3 donut chart.
内容的提问来源于stack exchange,提问作者jignesh patel

