在Highcharts人口金字塔图中心添加类别标签的技术咨询
Highcharts人口金字塔图:中心添加年龄标签并禁用Y轴的实现方案
问题描述
我正尝试将一些传统图表迁移至Highcharts,制作人口金字塔图并无问题,但我希望在图表中心以方框形式添加年龄类别标签并禁用y轴,请问有什么解决思路?是否需要使用自定义定位函数?
原实现代码
var categories = ['0-4', '5-9', '10-14', '15-19', '20-24', '25-29', '30-34', '35-39', '40-44', '45-49', '50-54', '55-59', '60-64', '65-69', '70-74', '75-79', '80-84', '85-89', '90-94', '95-99', '100 + ']; Highcharts.chart('container', { chart: { type: 'bar', marginRight:110, marginLeft:110 }, title: { text: 'Population Pyramid, Census ' }, plotOptions: { series: { stacking: 'normal', dataLabels: { enabled: true, inside: true } } }, subtitle: { enabled:false }, xAxis: [{ categories: categories, reversed: false, labels: { step: 1 } }, { // mirror axis on right side opposite: true, reversed: false, categories: categories, linkedTo: 0, labels: { step: 1 } }], yAxis: { title: { text: null }, labels: { formatter: function () { return Math.abs(this.value); } } }, tooltip: { shadow:false, formatter: function () { return '<b>' + this.series.name + ', age ' + this.point.category + '</b><br/>' + 'Population: ' + Highcharts.numberFormat(Math.abs(this.point.y), 0); } }, series: [{ dataLabels: [{ align: 'center', format: '({y})' }], name: 'Male', data: [9765,11755,13535,13275,13560,12610,13515,14210,14780,16485,18685,20530,20695,19720,16600,10585,5960,2835,985] }, { name: 'Female', data:[-9220,-11275,-12640,-12445,-12520,-12435,-14010,-15235,-16115,-17510,-19690,-21620,-21825,-20730,-17805,-11780,-7275,-3910,-2425] }] });
解决方案
1. 禁用Y轴
直接在yAxis配置中添加visible: false,即可隐藏整个Y轴(包括刻度、标签):
yAxis: { title: { text: null }, visible: false // 禁用Y轴 }
2. 中心添加带方框的年龄标签
不需要自定义定位函数,利用Highcharts内置的renderer工具,在图表加载完成后批量绘制背景框和标签文本。核心逻辑是:
- 通过
chart.events.load事件触发绘制操作 - 遍历年龄类别,计算每个标签的垂直位置(基于X轴每个类别的中心坐标)
- 用
renderer.rect()绘制背景方框,renderer.text()绘制年龄文本,两者居中对齐
修改后的完整代码
var categories = ['0-4', '5-9', '10-14', '15-19', '20-24', '25-29', '30-34', '35-39', '40-44', '45-49', '50-54', '55-59', '60-64', '65-69', '70-74', '75-79', '80-84', '85-89', '90-94', '95-99', '100 + ']; Highcharts.chart('container', { chart: { type: 'bar', marginRight:110, marginLeft:110, events: { load: function() { var chart = this; var xAxis = chart.xAxis[0]; var centerX = chart.plotWidth / 2 + chart.plotLeft; // 图表中心X坐标 var boxWidth = 60; // 背景框宽度 var boxHeight = 20; // 背景框高度 categories.forEach(function(category, index) { // 获取当前年龄类别的垂直中心坐标 var yPos = xAxis.toPixels(index, true) + xAxis.tickLength / 2; // 绘制背景方框 chart.renderer.rect(centerX - boxWidth/2, yPos - boxHeight/2, boxWidth, boxHeight, 3) .attr({ fill: '#f0f0f0', stroke: '#ccc', 'stroke-width': 1 }) .add(); // 绘制年龄标签文本 chart.renderer.text(category, centerX, yPos + 5) .attr({ align: 'center', verticalAlign: 'middle' }) .add(); }); } } }, title: { text: 'Population Pyramid, Census ' }, plotOptions: { series: { stacking: 'normal', dataLabels: { enabled: true, inside: true } } }, subtitle: { enabled:false }, xAxis: [{ categories: categories, reversed: false, labels: { enabled: false // 隐藏原X轴标签 } }, { // mirror axis on right side opposite: true, reversed: false, categories: categories, linkedTo: 0, labels: { enabled: false // 隐藏右侧镜像X轴标签 } }], yAxis: { title: { text: null }, visible: false // 禁用Y轴 }, tooltip: { shadow:false, formatter: function () { return '<b>' + this.series.name + ', age ' + this.point.category + '</b><br/>' + 'Population: ' + Highcharts.numberFormat(Math.abs(this.point.y), 0); } }, series: [{ dataLabels: [{ align: 'left', format: '{y}' }], name: 'Male', data: [9765,11755,13535,13275,13560,12610,13515,14210,14780,16485,18685,20530,20695,19720,16600,10585,5960,2835,985] }, { dataLabels: [{ align: 'right', format: '{y}' }], name: 'Female', data:[-9220,-11275,-12640,-12445,-12520,-12435,-14010,-15235,-16115,-17510,-19690,-21620,-21825,-20730,-17805,-11780,-7275,-3910,-2425] }] });
关键说明
- 隐藏了原X轴的左右标签,避免和中心标签重复
- 调整了男女数据标签的对齐方式(左对齐/右对齐),避免遮挡中心标签
- 背景框的尺寸、颜色可通过
rect()的参数自行调整 - 文本的位置可通过
renderer.text()的坐标参数微调
内容的提问来源于stack exchange,提问作者jdower27
相关产品推荐
相关产品推荐

