Angular 10中Highcharts环形进度条下方添加线性进度条的问题
解决方案:避免环形进度条与线性进度条重叠
针对你遇到的布局重叠问题,以下提供两种可行的实现方案,核心思路是通过空间隔离或手动布局控制来分离两类图表元素:
方案一:拆分容器,独立渲染两个图表
这是最直观且易维护的方案,将环形进度条和线性进度条放在两个独立的DOM容器中,各自初始化Highcharts实例,彻底避免布局冲突。
1. 调整组件模板的HTML结构
<!-- 环形进度条容器,固定高度预留空间 --> <div id="ring-chart" style="height: 300px;"></div> <!-- 线性进度条容器,与环形图拉开间距 --> <div id="progress-chart" style="height: 150px; margin-top: 20px;"></div>
2. 初始化环形进度条(复用原有代码,仅修改容器ID)
// 环形进度条初始化逻辑 new Highcharts.chart('ring-chart', { exporting: { enabled: false }, chart: { type: 'solidgauge', events: { render() { let chart = this, label1 = chart.series[0].dataLabelsGroup, label2 = chart.series[1].dataLabelsGroup; label1.translate(chart.marginRight, 0); label2.translate(chart.marginRight, chart.plotTop - label2.getBBox().height); } } }, legend: { enabled: false }, credits: { enabled: false }, pane: { startAngle: 180, background: this.getBackgroundSettingsForDepositStatusGraph() }, tooltip: { outside: true }, title: false, accessibility: { point: { valueSuffix: '' } }, xAxis: { tickInterval: 1, minorGridLineWidth: 0, labels: { align: 'right', useHTML: true, allowOverlap: true, step: 1, y: 3, style: { fontSize: '13px', color: "black" } }, lineWidth: 0, }, yAxis: { min: 0, max: 100, lineWidth: 0, tickPositions: [] }, plotOptions: { solidgauge: { dataLabels: { enabled: true, verticalAlign: 'middle' }, } }, series: [ { name: "Total", data: [{ color: Highcharts.getOptions().colors[0], radius: "115%", innerRadius: "110%", y: Math.round(this.data.total.percentage), dataLabels: { format: "{y}%", borderWidth: 0, style: { fontSize: "15px" } } }] }, { name: 'Amount', data: [{ color: Highcharts.getOptions().colors[2], radius: "105%", innerRadius: "100%", y: Math.round(this.data.amount.percentage), dataLabels: { format: "{y}%", borderWidth: 0, style: { fontSize: "15px" } } }] } ] });
3. 初始化线性进度条(用bar图表模拟,支持显示额外数据)
// 线性进度条初始化逻辑 new Highcharts.chart('progress-chart', { chart: { type: 'bar' }, exporting: { enabled: false }, credits: { enabled: false }, title: false, legend: { enabled: false }, xAxis: { categories: ['Total', 'Amount'], lineWidth: 0, tickWidth: 0, labels: { style: { fontSize: '14px', fontWeight: 'bold' } } }, yAxis: { min: 0, max: 100, lineWidth: 0, tickPositions: [], title: false }, tooltip: { enabled: false }, plotOptions: { bar: { borderRadius: 3, dataLabels: { enabled: true, align: 'right', // 自定义格式:百分比 + 额外数据 format: '{point.y}% | {point.extraData1} {point.extraData2}', style: { fontSize: '13px' } } } }, series: [{ data: [ { y: Math.round(this.data.total.percentage), color: Highcharts.getOptions().colors[0], extraData1: this.data.total.value1, // 替换为你的实际数据(如25) extraData2: this.data.total.value2 // 替换为你的实际数据(如60) }, { y: Math.round(this.data.amount.percentage), color: Highcharts.getOptions().colors[2], extraData1: this.data.amount.value1, extraData2: this.data.amount.value2 } ] }] });
方案二:同一容器内调整布局,用Renderer绘制线性进度条
如果希望保持单一容器,可通过扩展环形图的容器高度、预留底部空间,再用Highcharts的Renderer手动绘制线性进度条和文本,避免元素重叠。
修改原有环形图配置并添加绘制逻辑
new Highcharts.chart('container', { exporting: { enabled: false }, chart: { type: 'solidgauge', height: 450, // 增加容器总高度 spacingBottom: 150, // 预留底部空间给线性进度条 events: { render() { let chart = this; // 原有标签定位逻辑 let label1 = chart.series[0].dataLabelsGroup, label2 = chart.series[1].dataLabelsGroup; label1.translate(chart.marginRight, 0); label2.translate(chart.marginRight, chart.plotTop - label2.getBBox().height); // 清除上一次渲染的自定义元素,避免重复绘制 if (chart.customElements) { chart.customElements.forEach(el => el.destroy()); } chart.customElements = []; // 定义进度条基础参数 const barWidth = chart.plotWidth * 0.7; const barHeight = 20; const startX = chart.plotLeft + (chart.plotWidth - barWidth) / 2; const totalBarY = chart.plotTop + chart.plotHeight + 20; const amountBarY = totalBarY + barHeight + 15; // 绘制Total进度条 // 灰色背景条 const totalBg = chart.renderer.rect(startX, totalBarY, barWidth, barHeight, 3) .attr({ fill: '#e0e0e0' }) .add(); chart.customElements.push(totalBg); // 彩色进度条 const totalProgress = chart.renderer.rect(startX, totalBarY, (this.data.total.percentage / 100) * barWidth, barHeight, 3) .attr({ fill: Highcharts.getOptions().colors[0] }) .add(); chart.customElements.push(totalProgress); // 显示文本:Total 25 60 85% const totalText = chart.renderer.text( `Total ${this.data.total.value1} ${this.data.total.value2} ${Math.round(this.data.total.percentage)}%`, startX + 10, totalBarY + barHeight / 2 + 5 ).attr({ style: { fontSize: '14px' } }) .add(); chart.customElements.push(totalText); // 绘制Amount进度条 const amountBg = chart.renderer.rect(startX, amountBarY, barWidth, barHeight, 3) .attr({ fill: '#e0e0e0' }) .add(); chart.customElements.push(amountBg); const amountProgress = chart.renderer.rect(startX, amountBarY, (this.data.amount.percentage / 100) * barWidth, barHeight, 3) .attr({ fill: Highcharts.getOptions().colors[2] }) .add(); chart.customElements.push(amountProgress); const amountText = chart.renderer.text( `Amount ${this.data.amount.value1} ${this.data.amount.value2} ${Math.round(this.data.amount.percentage)}%`, startX + 10, amountBarY + barHeight / 2 + 5 ).attr({ style: { fontSize: '14px' } }) .add(); chart.customElements.push(amountText); } } }, // 其余原有配置(pane、xAxis、yAxis、series等)保持不变 // ... });
方案对比
- 方案一:代码逻辑清晰,两个图表独立维护,无耦合,适合后续需要单独调整样式或交互的场景;
- 方案二:保持单一容器,视觉上更紧凑,但需要手动管理自定义元素的渲染与销毁,适合布局要求严格的场景。
内容的提问来源于stack exchange,提问作者Athulya Ratheesh
相关产品推荐
相关产品推荐

