javascriptreactjschart.js

How to Make a Baseline Bar Behind Stacked Bars in Chart.js?


I’m trying to create a stacked bar chart in Chart.js where one specific bar (labeled "予想" - prediction) acts as a baseline or background layers. The goal is for this bar to sit visually behind other stacked bars, so it acts like a "container" that the other bars cumulatively fill up to.

Or in another way to explain, is like the other bars are filling the main bar. However, I am struggling stacking the main bar behind it.

I created a codepen with the example: https://codesandbox.io/p/sandbox/vigilant-wave-wnvsxn?file=%2Fsrc%2Fcomponents%2FEnergyUsageChart.js%3A22%2C1-88%2C1

  const chartData = {
    labels: ["今日"], // Only today
    datasets: [
      {
        label: "prediction",
        data: [1200], // Only data for today
        backgroundColor: "rgba(237, 239, 255, 0.5)",
        borderColor: "rgba(106, 122, 242, 1)",
        borderWidth: 1,
        borderDash: [5, 5],
        stack: "baseline",
      },
      {
        label: "air-c",
        data: [300],
        backgroundColor: "rgba(88, 181, 247, 1)",
        stack: "filling",
      },
      {
        label: "illumination",
        data: [300],
        backgroundColor: "rgba(71, 68, 222, 1)",
        stack: "filling",
      },
      {
        label: "cooling-case",
        data: [300],
        backgroundColor: "rgba(157, 201, 210, 1)",
        stack: "filling",
      },
      {
        label: "others",
        data: [100],
        backgroundColor: "rgba(182, 193, 200, 1)",
        stack: "filling",
      },
    ],
  };

  const options = {
    responsive: true,
    maintainAspectRatio: false,
    scales: {
      x: { stacked: true },
      y: {
        stacked: true,
        max: 2000,
        ticks: { stepSize: 1000 },
      },
    },
    plugins: {
      legend: { display: false },
      datalabels: { display: false },
      tooltip: {
        callbacks: {
          label: (context) => {
            const label = context.dataset.label || "";
            return `${label}: ${new Intl.NumberFormat("ja-JP", {
              style: "currency",
              currency: "JPY",
            }).format(context.parsed.y)}`;
          },
        },
      },
    },
  };

Thanks!


Solution

  • For the "baseline" object, you should add grouped property with false to achieve the result.

    {
        label: "prediction",
        data: [1200], // Only data for today
        backgroundColor: "rgba(237, 239, 255, 0.5)",
        borderColor: "rgba(106, 122, 242, 1)",
        borderWidth: 1,
        borderDash: [5, 5],
        stack: "baseline",
        grouped: false,
    },
    

    Demo @ Code Sandbox