DIPAK AGRAWAL
DIPAK AGRAWAL

Reputation: 1

Split legend in chart js

I have a line chart with 4 legends, I want to separate it 2 by 2 (2 in top and 2 in down)

enter image description here

    const chart = new Chart(ctx, {
        type: 'line',
        options: {
            responsive: true,
            maintainAspectRatio: false,
            bezierCurve: false,
            legend: {
                position: 'bottom',
                align: 'center',
                display: true,
            },
            hover: true,
            scales: {
                xAxes: [{
                    scaleLabel: {
                        display: true,
                        labelString: 'Date',
                        fontColor: "green",
                        fontSize: 15
                    },
                    ticks: {
                        fontColor: 'green'
                    },
                    gridLines: {
                        color: "rgba(0, 0, 0, 0)",
                    },
                }],
                yAxes: [{
                        scaleLabel: {
                            display: true,
                            labelString: 'F/R Ratio',
                            fontColor: "blue",
                            fontSize: 15,
                        },
                        id: 'A',
                        type: 'linear',
                        position: 'left',
                        ticks: {
                            fontColor: 'blue'
                        },
                        gridLines: {
                            color: "rgba(0, 0, 0, 0)",
                        },
    
                    },
                    {
                        scaleLabel: {
                            display: true,
                            labelString: 'Peak Pressure (kPa)',
                            fontColor: "red",
                            fontSize: 15
                        },
                        id: 'B',
                        type: 'linear',
                        position: 'right',
                        ticks: {
                            fontColor: 'red'
                        },
                        gridLines: {
                            zeroLineColor: '#ff0000',
                            display: true,
                            drawOnChartArea: false
                        },
    
                    },
                ]
            },
            layout: {
                padding: {
                    left: 20,
                    right: 20,
                    top: 20,
                    bottom: 0
                }
            },
            title: {
                display: true,
                text: 'Progress Bar',
                fontSize: 18
            }
        },
        data: {
            labels: ["08-08-2021", "09-08-2021", "15-08-2021", "16-08-2021", "20-08-2021"],
            datasets: [{
                    label: 'Left F/R Ratio',
                    yAxisID: 'A',
                    data: [100, 96, 84, 76, 69],
                    lineTension: 0,
                    backgroundColor: [
                        'rgba(99,132,255, 0.2)'
                    ],
                    borderColor: [
                        'rgba(99,132,255,1)'
                    ],
                    borderWidth: 1,
                    pointRadius: 4
                },
                {
                    label: 'Right F/R Ratio',
                    yAxisID: 'A',
                    data: [10, 96, 74, 75, 6],
                    lineTension: 0,
                    backgroundColor: [
                        'rgba(99, 132, 255, 0.4)'
                    ],
                    borderColor: [
                        'rgba(99,132,255,1)'
                    ],
                    borderWidth: 1,
                    pointRadius: 4
                },
                {
                    label: 'Left Peak Pressure',
                    yAxisID: 'B',
                    data: [1, 1, 1, 1, 0],
                    lineTension: 0,
                    backgroundColor: [
                        'rgba(255,99,132, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255,99,132,1)'
                    ],
                    borderWidth: 1,
                    pointRadius: 4
                },
                {
                    label: 'Right Peak Pressure',
                    yAxisID: 'B',
                    data: [5, 10, 5, 1, 0],
                    lineTension: 0,
                    backgroundColor: [
                        'rgba(255,99,132,0.4)'
                    ],
                    borderColor: [
                        'rgba(255,99,132,1)'
    
                    ],
                    borderWidth: 1,
                    pointRadius: 4
                }        
            ]
        },
    });

Here is the actual code which I used to genertae my canvas using chart js with 2 Y-axes, one for F/R ratio and another for Peak pressure.

I also want to format the x-axes filter the x-axes with week, month and year.

Upvotes: 0

Views: 2436

Answers (1)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48630

You could create your own HTML Legend and apply a CSS grid layout. See the HTML legend demo.

const getOrCreateLegendList = (chart, id) => {
  const legendContainer = document.getElementById(id);
  let listContainer = legendContainer.querySelector('ul');

  if (!listContainer) {
    listContainer = document.createElement('ul');
    listContainer.style.display = 'flex';
    listContainer.style.flexDirection = 'row';
    listContainer.style.margin = 0;
    listContainer.style.padding = 0;

    legendContainer.appendChild(listContainer);
  }

  return listContainer;
};

const createLegendItem = (item, chart, legend) => {
  const li = document.createElement('li');
  li.style.alignItems = 'center';
  li.style.cursor = 'pointer';
  li.style.display = 'flex';
  li.style.flexDirection = 'row';
  li.style.marginLeft = '10px';

  li.onclick = () => {
    const { type } = chart.config;
    if (type === 'pie' || type === 'doughnut') {
      // Pie and doughnut charts only have a single dataset and visibility is per item
      chart.toggleDataVisibility(item.index);
    } else {
      chart.setDatasetVisibility(item.datasetIndex, !chart.isDatasetVisible(item.datasetIndex));
    }
    chart.update();
  };

  // Color box
  const boxSpan = document.createElement('span');
  boxSpan.style.background = item.fillStyle;
  boxSpan.style.borderColor = item.strokeStyle;
  boxSpan.style.borderWidth = item.lineWidth + 'px';
  boxSpan.style.display = 'inline-block';
  boxSpan.style.height = '20px';
  boxSpan.style.marginRight = '10px';
  boxSpan.style.width = '20px';

  // Text
  const textContainer = document.createElement('p');
  textContainer.style.color = item.fontColor;
  textContainer.style.margin = 0;
  textContainer.style.padding = 0;
  textContainer.style.textDecoration = item.hidden ? 'line-through' : '';

  const text = document.createTextNode(item.text);
  textContainer.appendChild(text);

  li.appendChild(boxSpan);
  li.appendChild(textContainer);
  legend.appendChild(li);
};

const htmlLegendPlugin = {
  id: 'htmlLegend',
  afterUpdate(chart, args, options) {
    const ul = getOrCreateLegendList(chart, options.containerID);

    // Remove old legend items
    while (ul.firstChild) ul.firstChild.remove();

    // Reuse the built-in legendItems generator
    chart.options.plugins.legend.labels.generateLabels(chart)
      .forEach(item => createLegendItem(item, chart, ul));
  }
};

const seriesDefaults = {
  fill: true,
  borderWidth: 1,
};

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      ...seriesDefaults,
      label: 'Left F/R Ratio',
      data: [12, 19, 3, 5, 2, 3],
      borderColor: 'rgba(192, 192, 255, 1)',
      backgroundColor: 'rgba(192 ,192, 255, 0.5)'
    }, {
      ...seriesDefaults,
      label: 'Right F/R Ratio',
      data: [11, 5, 8, 3, 7, 5],
      borderColor: 'rgba(64, 64, 255, 1)',
      backgroundColor: 'rgba(64 ,64, 255, 0.5)'
    }, {
      ...seriesDefaults,
      label: 'Left Peak Pressure',
      data: [19, 3, 5, 2, 3, 12],
      borderColor: 'rgba(255, 192, 192, 1)',
      backgroundColor: 'rgba(255, 192, 192, 0.5)'
    }, {
      ...seriesDefaults,
      label: 'Right Peak Pressure',
      data: [7, 11, 5, 8, 3, 7],
      borderColor: 'rgba(255, 64, 64, 1)',
      backgroundColor: 'rgba(255, 64 ,64, 0.5)'
    }]
  },
  options: {
    plugins: {
      htmlLegend: {
        containerID: 'legend-container'
      },
      legend: {
        display: false
      }
    }
  },
  plugins: [htmlLegendPlugin]
}

const ctx = document.getElementById('chart').getContext('2d');

new Chart(ctx, options);
html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.chart-wrapper {
  display: flex;
  flex-direction: column;
}

.chart {
  display: flex;
  flex: 1;
}

#legend-container {
  display: flex;
  justify-content: center;
  padding: 0.5em;
}

#legend-container ul {
  display: grid !important;
  grid-template-columns: repeat(2, 1fr);
  grid-row-gap: 0.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<div class="chart-wrapper">
  <canvas id="chart"></canvas>
  <div id="legend-container"></div>
</div>

Upvotes: 1

Related Questions