如何在React中使用Chart.js实现柱状图沿水平阈值线分段显示多色
实现方案
核心逻辑是利用已开启的堆叠柱状图特性,将单根柱子拆为上下两个堆叠的分段,分别对应100以下的灰色段和超出100的绿色段,即可实现需求。
具体修改说明
- 拆分数据集:将原单组数据拆为两组堆叠数据
- 底段数据集:每个值取原数值和100的较小值,固定背景色为灰色
- 超量段数据集:每个值取原数值减100后和0的较大值,固定背景色为绿色
- 调整数据标签:仅在有效段显示总数值,避免重复展示
- 调整圆角样式:仅给最上层的超量段设置顶部圆角,保证柱子视觉连贯
- 修正原有注解配置位置:chartjs-plugin-annotation的配置需要放在
plugins.annotation层级下才会生效
完整修改后代码
import { Bar, Chart } from 'react-chartjs-2'; import annotationPlugin from "chartjs-plugin-annotation"; import ChartDataLabels from "chartjs-plugin-datalabels"; // 修正插件注册写法 Chart.register(annotationPlugin, ChartDataLabels); const chartColors = { yellow: '#F4D068', green: '#4CC26F', gray: '#EBEBEB' }; // 原数据单独抽离 const originalData = [65, 140, 130, 200, 56, 35, 80]; const colorChangeValue = 100; const data = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], // 补全对应7个数据的标签 datasets: [ // 底段灰色数据集 { label: 'base', backgroundColor: chartColors.gray, borderColor: '#EBEBEB', borderWidth: 1, borderRadius: 0, data: originalData.map(v => Math.min(v, colorChangeValue)), }, // 超量绿色数据集 { label: 'exceed', backgroundColor: chartColors.green, borderColor: '#EBEBEB', borderWidth: 1, // 仅设置顶部圆角 borderRadius: { topLeft: 10, topRight: 10, bottomLeft: 0, bottomRight: 0 }, data: originalData.map(v => Math.max(v - colorChangeValue, 0)), } ], }; export default function BarChart() { return ( <Bar data={data} width={100} height={70} options={{ scales: { x: { stacked: true, grid: { display: false, }, }, y: { stacked: true, grid: {}, ticks: { maxTicksLimit: 1 } } }, plugins: { legend: { display: false }, title: { display: true, text: "범례1", padding: { bottom: 30 }, weight: "bold", color: "#00325c", font: { size: 13 }, align: "start" }, datalabels: { display: function(context) { // 仅在顶层展示标签,超量段值为0时在底段展示 return context.datasetIndex === 1 || originalData[context.dataIndex] < colorChangeValue; }, color: "black", anchor: 'end', align: 'top', formatter: function (value, ctx) { // 计算并显示总数值 const total = originalData[ctx.dataIndex]; return total + "%"; } }, annotation: { annotations: { myHorizontalLine: { type: "line", scaleID: "y", borderWidth: 3, borderColor: "#333333", value: 100, borderDash: [8, 8], label: { font: { weight: "normal" }, rotation: "auto", enabled: true } } } } } }} /> ) }
内容的提问来源于stack exchange,提问作者ssksksks
相关产品推荐
相关产品推荐

