如何在单个Highcharts图表中为各饼图添加独立标题/图例?
为Highcharts单图表内的多饼图添加独立标题/图例(支持整体导出)
需求描述
我使用Highcharts在单个图表中展示4组饼图系列,页面仅有一个通用标题,但希望为每个饼图添加独立标题(如PIE 1、PIE 2等)。由于需要将4个饼图一起导出为单张PNG/PDF,无法拆分为独立图表,请问该如何实现?
原代码
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <script type="text/javascript" src="https://code.highcharts.com/highcharts.js"></script> <script type="text/javascript" src="https://code.highcharts.com/highcharts-3d.js"></script> <script type="text/javascript" src="https://code.highcharts.com/modules/exporting.js"></script> <script type="text/javascript" src="https://code.highcharts.com/modules/export-data.js"></script> <script type="text/javascript" src="https://code.highcharts.com/modules/accessibility.js"></script> <script type="text/javascript"> $(document).ready(function () { $.ajaxSetup({ cache: false }); $.ajaxSetup({ 'async': false }); var myData = [18, 635, 21, 177, 20, 165, 22, 163, 24, 162, 25, 145, 19, 143, 23, 139, 26, 112, 27, 110, 28, 104, 30, 91, 29, 88, 31, 68, 32, 57, 36, 55, 34, 53, 33, 51, 35, 46, 37, 44, 39, 42, 43]; var mySeries = []; for (var i = 0; i < myData.length; i++) { if (i % 2 == 0) { mySeries.push({ name: "DATO par " + i, y: myData[i], sliced: true, selected: true }); } else mySeries.push(["DATO " + i, myData[i]]); } Highcharts.setOptions({ lang: { //修改选项文本 downloadPNG: "Descargar PNG", downloadPDF: "Descargar PDF" } }); Highcharts.chart('container', { chart: { type: 'pie', options3d: { enabled: true, alpha: 45, beta: 0 }, height: 700 }, title: { text: 'Informe Estadístico', align: 'left' }, subtitle: { text: 'Periodo: 01/01/2023 - 31/03/2023', align: 'left' }, accessibility: { point: { valueSuffix: '%' } }, tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>' }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', depth: 35, dataLabels: { enabled: true, format: '{point.name}' } } }, credits: { enabled: false }, exporting: { buttons: { contextButton: { menuItems: ["downloadPNG", "downloadPDF"] } }, sourceWidth: 900 }, //exporting: { enabled: false }, -> 隐藏所有导出选项 series: [ //图表1 { size: 250, center: [200, 150], type: 'pie', name: 'Porcentaje', description: 'PIE 1', //无效 data: mySeries }, //图表2 { size: 250, center: [650, 150], type: 'pie', name: 'Share', data: [ ['Samsung', 23], ['Apple', 18], { name: 'Xiaomi', y: 12, sliced: true, selected: true }, ['Oppo*', 9], ['Vivo', 8], ['Others', 30] ] }, //图表3 { size: 250, center: [200, 450], type: 'pie', name: 'Share', data: [ ['Samsung', 23], ['Apple', 18], { name: 'Xiaomi', y: 12, sliced: true, selected: true }, ['Oppo*', 9], ] }, //图表4 { size: 250, center: [650, 450], type: 'pie', name: 'Share', data: [ ['Apple', 18], { name: 'Xiaomi', y: 12, sliced: true, selected: true }, ['Oppo*', 9], ['Vivo', 8] ] } ] }); }); </script> <figure class="highcharts-figure"> <div id="container"></div> <p class="highcharts-description"> <i>*OPPO includes OnePlus since Q3 2021</i><br/><br/> Chart demonstrating the use of a 3D pie layout. </p> </figure> </asp:Content>
解决方案
方法一:使用Renderer手动绘制独立标题
利用Highcharts的rendererAPI在图表加载完成后,为每个饼图绘制自定义标题,精准定位且支持导出。
修改代码:
在chart配置中添加events.load回调:
chart: { type: 'pie', options3d: { enabled: true, alpha: 45, beta: 0 }, height: 700, events: { load: function() { // 定义每个饼图的标题 const pieTitles = ['PIE 1', 'PIE 2', 'PIE 3', 'PIE 4']; this.series.forEach((series, index) => { const [centerX, centerY] = series.options.center; const radius = series.options.size / 2; // 在饼图上方绘制标题并居中 const titleText = this.renderer.text( pieTitles[index], centerX, centerY - radius - 20 ) .css({ fontSize: '16px', fontWeight: 'bold', color: '#333' }) .add(); // 调整x坐标实现文本居中 titleText.attr({ x: centerX - titleText.getBBox().width / 2 }); }); } } },
方法二:用虚拟数据点模拟标题
通过添加y值为0的虚拟数据点,利用dataLabels显示标题,隐藏虚拟点的图形,不影响饼图比例计算。
修改代码(以第一个饼图为例):
// 图表1 { size: 250, center: [200, 150], type: 'pie', name: 'Porcentaje', data: [ // 虚拟点用于显示标题 { name: 'PIE 1', y: 0, color: 'transparent', // 隐藏饼图切片 dataLabels: { enabled: true, format: '{point.name}', y: -100, // 调整到饼图上方 style: { fontSize: '16px', fontWeight: 'bold', color: '#333' } } }, ...mySeries // 原数据 ] },
关键说明
- 两种方法都支持整体导出,绘制的标题会包含在导出的PNG/PDF中
- 可根据需求调整标题的位置、字体大小、颜色等样式
- 方法一的灵活性更高,适合复杂布局;方法二更简单,无需额外事件处理
内容的提问来源于stack exchange,提问作者Keras-JOB
相关产品推荐
相关产品推荐

