Reputation: 1
I have a line chart with 4 legends, I want to separate it 2 by 2 (2 in top and 2 in down)
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
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