如何在Highcharts堆叠柱状图的每个分段间添加线条?
How to Add Lines Between Segments in Highcharts Stacked Column Charts
Hey there! I’ve tackled this exact problem before—regular column chart line solutions don’t work here because stacked segments have dynamic positions based on cumulative values above and below them. Here’s a reliable way to add those dividing lines between each stacked segment:
Core Approach
We’ll use Highcharts’ built-in renderer.path() method to draw horizontal lines across each segment’s top edge. The key is calculating the exact position of each segment on the chart, and ensuring the lines update when the chart is redrawn (like on window resize or data changes).
Step-by-Step Implementation
- Attach Chart Events: Listen to the
loadandredrawevents to trigger our line-drawing logic—this ensures lines stay in place if the chart updates. - Create a Reusable Method: Write a custom function to calculate segment positions, draw lines, and clean up old lines to avoid duplicates.
- Calculate Segment Coordinates: Use each point’s
shapeArgsproperty (which holds the x, y, width, and height of the segment) to find where the line should sit. - Draw the Lines: Use the renderer to create horizontal lines across the top of each non-top segment.
Full Code Example
Highcharts.chart('container', { chart: { type: 'column', events: { load: function() { this.drawSegmentLines(); }, redraw: function() { this.drawSegmentLines(); } }, // Custom method to handle segment line drawing drawSegmentLines: function() { // Clear existing lines to prevent duplication on redraw if (this.segmentLines) { this.segmentLines.forEach(line => line.destroy()); } this.segmentLines = []; const chart = this; const allSeries = chart.series; allSeries.forEach((series, seriesIndex) => { // Skip non-stacked series if any exist if (!series.options.stack) return; series.points.forEach(point => { const segmentShape = point.shapeArgs; // Calculate line start/end x positions (full width of the column) const lineStartX = segmentShape.x - segmentShape.width / 2; const lineEndX = segmentShape.x + segmentShape.width / 2; // Line y position = top edge of the current segment const lineY = segmentShape.y; // Skip drawing a line for the topmost segment of each column const isTopSegment = seriesIndex === allSeries.length - 1 || !allSeries[seriesIndex + 1].points[point.index] || allSeries[seriesIndex + 1].options.stack !== series.options.stack; if (isTopSegment) return; // Create and style the line const segmentLine = chart.renderer.path([ 'M', lineStartX, lineY, // Move to start point 'L', lineEndX, lineY // Draw line to end point ]) .attr({ stroke: '#333', // Line color 'stroke-width': 1, // Line thickness // Optional: Make it dashed with 'stroke-dasharray': '3,3' }) .add(); this.segmentLines.push(segmentLine); }); }); } }, title: { text: 'Stacked Columns with Segment Dividers' }, xAxis: { categories: ['Q1', 'Q2', 'Q3', 'Q4'] }, yAxis: { min: 0, title: { text: 'Total Value' } }, plotOptions: { column: { stacking: 'normal' } }, series: [ { name: 'Product A', data: [4, 3, 5, 2], stack: 'sales' }, { name: 'Product B', data: [2, 4, 3, 6], stack: 'sales' }, { name: 'Product C', data: [5, 2, 4, 3], stack: 'sales' } ] });
Key Notes
- Multiple Stacks Support: The code checks for
series.options.stack, so it works even if you have separate stacked groups on the same chart. - Styling Flexibility: Adjust the
stroke,stroke-width, or addstroke-dasharrayto match your design needs. - Top Segment Control: The
isTopSegmentcheck skips drawing a line above the very top of each column—remove this if you want a line there too.
内容的提问来源于stack exchange,提问作者Artem Aleksiienko
相关产品推荐
相关产品推荐

