I tried to add multiple charts in one page, but had the error Canvas is already in use. Chart with ID '0' must be destroyed before the canvas can be reused.
After research, I read that I had to set my canvas in div because :
Detecting when the canvas size changes can not be done directly from the CANVAS element. Chart.js uses its parent container to update the canvas render and display sizes. However, this method requires the container to be relatively positioned and dedicated to the chart canvas only. Responsiveness can then be achieved by setting relative values for the container size
So I did, but I still have the same error.
//chart1
const ctx = document.getElementById('chart1').getContext('2d')
const data1 = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
}]
}
const options1 = {
scales: {
y: {
beginAtZero: true
}
}
}
const myChart1 = new Chart(ctx, {
type: 'doughnut',
data: data1,
options: options1
})
//chart2
const ctx2 = document.getElementById('chart2').getContext('2d')
const data2 = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
}]
}
const options2 = {
scales: {
y: {
beginAtZero: true
}
}
}
const myChart2 = new Chart(ctx, {
type: 'line',
data: data2,
options: options2
})
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GraphJS</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<div style="width: 400px; height: 400px; margin: 0 auto 100px auto;">
<h1 style="text-align: center;">Tier 1</h1>
<canvas id="chart1"></canvas>
</div>
<div style="width: 400px; height: 400px; margin: 0 auto 100px auto;">
<h1 style="text-align: center;">Category</h1>
<canvas id="chart2"></canvas>
</div>
<script src="./index.js"></script>
</body>
</html>
Any idea where is my mistake ?
You are passing ctx as a parameter for chart2, which should be ctx2. Right now both of your graphs are pointing to same document element i.e. to element with id chart1.
const myChart2 = new Chart(ctx2, {
type: 'line',
data: data2,
options: options2
})
Just do this
Related
// Set Chart Global Variables
let x_values = [0];
let y_values = [0];
let new_number = 0;
let index = 0;
// Intialize The Chart Canvas
let ctx = document.getElementById('chart_canvas').getContext('2d');
// Create New Line Chart
my_chart = new Chart(ctx, {
type: "line",
data: {
labels: [x_values[0]],
datasets: [{
backgroundColor: [],
fill: true,
pointStyle: "circle",
label: "Values",
data: [y_values[0]]
}]
}
});
// ------ Local Functions ------
function add() {
index = x_values.length;
new_number += 10;
my_chart.data.labels.push(index);
x_values.push(index);
my_chart.data.datasets.forEach((dataset) => {
dataset.data.push(new_number);
//The line below might be wrong since it is not changing the background color.
dataset.backgroundColor.push("#88c0d080");
});
my_chart.update();
}
function subtract() {
index = x_values.length;
new_number -= 10;
my_chart.data.labels.push(index);
x_values.push(index);
my_chart.data.datasets.forEach((dataset) => {
dataset.data.push(new_number);
//This line below might be wrong since it is not changing the background color.
dataset.backgroundColor.push("#bf616a80");
});
my_chart.update();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Chart.js Line Chart</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js" integrity="sha512-sW/w8s4RWTdFFSduOTGtk4isV1+190E/GghVffMA9XczdJ2MDzSzLEubKAs5h0wzgSJOQTRYyaz73L3d6RtJSg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<button type="button" onclick="add()" id="btnAdd">Add 10</button>
<button type="button" onclick="subtract()" id="btnSubtract">Subtract 10</button>
<canvas id="chart_canvas">Your browser does not support the HTML5 canvas tag.</canvas>
</body>
</html>
Expected Behavior:
When the "Add 10" button is clicked, a new point entry needs to be added with a backgroundColor fill
color of teal (#88c0d080).
When the "subtract 10" button is clicked, a new point entry needs to be added with a backgroundColor fill color of red (#bf616a80).
Current Behavior:
Only the point background color is being changed rather than the backgroundColor fill color.
Your help will be much appreciated.
You can use segment styling that update dynamicly when you add new data:
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'orange',
fill: true,
segment: {
backgroundColor: (ctx) => (ctx.p0.parsed.y > ctx.p1.parsed.y ? 'red' : 'teal')
}
}]
},
options: {}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
const c = new Chart(ctx, options);
document.getElementById('add').addEventListener('click', () => {
c.data.labels.push(c.data.labels.length);
c.data.datasets[0].data.push(c.data.datasets[0].data[c.data.datasets[0].data.length - 1] + 10)
c.update()
});
document.getElementById('subb').addEventListener('click', () => {
c.data.labels.push(c.data.labels.length);
c.data.datasets[0].data.push(c.data.datasets[0].data[c.data.datasets[0].data.length - 1] - 10)
c.update()
});
<body>
<button id="add">
Add 10
</button>
<button id="subb">
Subtract 10
</button>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
</body>
The Chart Spans across the entire Web Page and I cant resize it. I've tried seting the height/width of the canvas and the canvas with no luck.
Here is my Html:
<div id="chartbox">
<canvas id="myChart" display="block"></canvas>
</div>
<script>
var xaxis = [1,2,3,4,5]
var yaxis = [2,3,4,5,6]
var thisChart = new Chart(document.getElementById("myChart"), {
type: 'line',
options: {
responsive: true
},
data: {
labels: xaxis,
datasets: [
{
data: yaxis,
label: "Test",
borderColor: "#3e95cd",
}
]
}
});
</script>
If you are styling the canvas element directly with non relative values you need to set responsive to false in the options, if you are styling the width with relative values you need to apply them to the surrounding div
https://www.chartjs.org/docs/master/configuration/responsive.html
I hope my answer is helpful to you, you just have to specify certain CSS rules for the parent element of the graphic.
var xaxis = [1,2,3,4,5]
var yaxis = [2,3,4,5,6]
var thisChart = new Chart(document.getElementById("myChart"), {
type: 'line',
options: {
responsive: true
},
data: {
labels: xaxis,
datasets: [
{
data: yaxis,
label: "Test",
borderColor: "#3e95cd",
}
]
}
});
#chartbox {
display: block;
width: 400px;
height: 400px;
}
<div id="chartbox">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
Now,I would like to implement a polar area chart like following picture with Chart.js and Canvas.
How should I do to implement it?
So far,I tried the following code but it does not work.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<style media="screen" type="text/css">#container{width:100%;height:100%;top:0;left:0;right:0;bottom:0;position:absolute;}</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const canvas = document.getElementById('chart')
const ctx = canvas.getContext('2d');
const gradient = ctx.createRadialGradient(75, 50, 5, 90, 60, 100)
const [ w , h ] = [ canvas.clientWidth , canvas.clientHeight ];
gradient.addColorStop(0.0 , 'rgb(255,0,0)');
gradient.addColorStop(0.5 , 'rgb(0,255,0)');
const data = {
backgroundColor: [gradient,gradient,gradient,gradient,gradient],
labels: ['First label', 'Second label', 'Third label', 'Fourth label', 'Fifth label'],
datasets: [
{
label: 'First dataset',
backgroundColor: gradient,
data: [50, 20, 40, 50, 22]
}
]
};
const options = {
tooltips: {
mode: 'label'
},
};
const myRadarChart = new Chart(ctx, {
type: 'polarArea',
data,
options
});
});
</script>
</head>
<body>
<canvas id="chart" width="${width}" height="${width}" />
</body>
</html>
Try like this:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<style media="screen" type="text/css">#container{width:100%;height:100%;top:0;left:0;right:0;bottom:0;position:absolute;}</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const canvas = document.getElementById('chart')
const ctx = canvas.getContext('2d');
const [ w , h ] = [ canvas.clientWidth , canvas.clientHeight ];
const r = 300;
const gradient = ctx.createRadialGradient(w, h*1.2, 0, w, h, r * 0.6);
gradient.addColorStop(0.0 , 'rgb(255,0,0)');
gradient.addColorStop(1 , 'rgb(0,255,0)');
const data = {
backgroundColor: [gradient,gradient,gradient,gradient,gradient],
labels: ['First label', 'Second label', 'Third label', 'Fourth label', 'Fifth label'],
datasets: [
{
label: 'First dataset',
backgroundColor: gradient,
data: [50, 20, 40, 50, 22]
}
]
};
const options = {
tooltips: {
mode: 'label'
},
};
const myRadarChart = new Chart(ctx, {
type: 'polarArea',
data,
options
});
});
</script>
</head>
<body>
<canvas id="chart" width="${width}" height="${width}" />
</body>
</html>
The code is good! It's only a case of using the canvas width, height and radius of the chart's largest circle to position the gradient correctly. Minor adjustments can also be made if the final chart position in the canvas shifts (e.g. where a different canvas aspect ratio is used).
From there, it is simple to create a new gradient in the same way for each combination of colours you wish to use.
I am using Chart.js and this API to create a line graph of covid-19 cases in Australia.
However, the API data is not loading in the chart until I do something like inspect an element on the page or resize the window.
Here is my JS file:
window.onload = function() {
let dates = [];
let confirmedCases = [];
let confirmedRecovered = [];
let confirmedDeaths = [];
function addArrayFunc(date, confirmed, recovered, deaths) {
dates.push(date);
confirmedCases.push(confirmed);
confirmedRecovered.push(recovered);
confirmedDeaths.push(deaths);
}
fetch("https://pomber.github.io/covid19/timeseries.json")
.then(response => response.json())
.then(cases => {
cases["Australia"].forEach(({
date,
confirmed,
recovered,
deaths
}) =>
addArrayFunc(date, confirmed, recovered, deaths)
)
})
const ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: dates,
datasets: [{
label: 'Confirmed',
borderColor: 'pink',
backgroundColor: 'pink',
fill: 'false',
data: confirmedCases
},
{
label: 'Recovered',
borderColor: 'blue',
backgroundColor: 'blue',
fill: 'false',
data: confirmedRecovered
},
{
label: 'Deaths',
borderColor: 'green',
backgroundColor: 'green',
fill: 'false',
data: confirmedDeaths
}
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Covid-19 Cases in Australia'
},
}
});
}
Here is my html file:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Confirmed Covid-19 cases in Australia</title>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
width: 75%;
}
</style>
<script src="script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
</head>
<body>
<canvas id="myChart"></canvas>
</body>
</html>
I believe I am creating the chart before the data has arrived from the URL but I have no idea have to rectify that. Is this something async/await or watch could fix? How would I go implementing that?
Any help would be greatly appreciated.
Since fetch makes an asynchronous call, you need to create your chart once the response is received. Therefore, simply place the chart creation code inside .then and it will work as shown below.
window.onload = function() {
let dates = [];
let confirmedCases = [];
let confirmedRecovered = [];
let confirmedDeaths = [];
function addArrayFunc(date, confirmed, recovered, deaths) {
dates.push(date);
confirmedCases.push(confirmed);
confirmedRecovered.push(recovered);
confirmedDeaths.push(deaths);
}
fetch("https://pomber.github.io/covid19/timeseries.json")
.then(response => response.json())
.then(cases => {
cases["Australia"].forEach(({
date,
confirmed,
recovered,
deaths
}) =>
addArrayFunc(date, confirmed, recovered, deaths)
)
new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
labels: dates,
datasets: [{
label: 'Confirmed',
borderColor: 'pink',
backgroundColor: 'pink',
fill: 'false',
data: confirmedCases
},
{
label: 'Recovered',
borderColor: 'blue',
backgroundColor: 'blue',
fill: 'false',
data: confirmedRecovered
},
{
label: 'Deaths',
borderColor: 'green',
backgroundColor: 'green',
fill: 'false',
data: confirmedDeaths
}
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Covid-19 Cases in Australia'
},
}
});
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="90"></canvas>
Hi guys i am using ChartJS for creating pie charts,it is pretty good.In my project i have to create many pie charts, all the charts will have the same labels and background color.In the code given below i am giving the backgroundColor and label while creating the pie charts individually.Is there any way to make label and background color common for all the charts.
<!DOCTYPE html>
<html>
<head>
<title> ChartJS tutorial </title>
<style type="text/css">
#pie-charts-wrapper{
width:1000px;
margin-left:auto;
margin-right:auto;
}
.pie-chart-wrapper{
width:500px;
height:300px;
box-sizing:border-box;
float:left;
padding:20px;
}
</style>
</head>
<body>
<div id="pie-charts-wrapper">
<div class="pie-chart-wrapper">
<canvas id="pieChart1" width="500px" height="300" ></canvas>
</div>
<div class="pie-chart-wrapper">
<canvas id="pieChart2" width="500px" height="300" ></canvas>
</div>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js" ></script>
<script type="text/javascript">
var ctx1 = document.getElementById("pieChart1");
var ctx2 = document.getElementById("pieChart2");
var data1 = {
labels: ['Signed','Not Signed'],
datasets: [{
backgroundColor:['#1abc9c','#34495e'],
data: [10, 25],
}],
};
var data2 = {
labels: ['Signed','Not Signed'],
datasets: [{
backgroundColor:['#1abc9c','#34495e'],
data: [15, 2]
}],
};
var myPieChart1 = new Chart(ctx1,{
type: 'pie',
data: data1
});
var myPieChart2 = new Chart(ctx2,{
type: 'pie',
data: data2
});
</script>
</body>
</html>
If speaking technically then yes, there is a way. Though it's not recommended, as that's not how ChartJS meant to work, therefore no built-in functionality either.
To accomplish this you would rather go for kind of a hacky solution, which is to use a plugin, like the following :
Chart.plugins.register({
beforeInit: function(chart) {
chart.data.labels = ['Signed', 'Not Signed'];
chart.data.datasets[0].backgroundColor = ['#1abc9c', '#34495e'];
}
});
* add this at the beginning of your script
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ
Chart.plugins.register({
beforeInit: function(chart) {
chart.data.labels = ['Signed', 'Not Signed'];
chart.data.datasets[0].backgroundColor = ['#1abc9c', '#34495e'];
}
});
var ctx1 = document.getElementById("pieChart1");
var ctx2 = document.getElementById("pieChart2");
var data1 = {
datasets: [{
data: [10, 25],
}]
};
var data2 = {
datasets: [{
data: [15, 2]
}]
};
var myPieChart1 = new Chart(ctx1, {
type: 'pie',
data: data1
});
var myPieChart2 = new Chart(ctx2, {
type: 'pie',
data: data2
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="pieChart1" width="500px" height="300"></canvas>
<canvas id="pieChart2" width="500px" height="300"></canvas>