I have made my bar-chart to a line-chart with a init and destroy function but I would like to add different data and labels in the new chart, so the line-chart contains labels like "palm oil", "sunflower oil", "olive oil" etc. but the bar-chart keeps the original data . How do I do this? When I add data to the init function, the whole chart just disappears.
<script>
var canvas = document.getElementById("barChart");
var ctx = canvas.getContext('2d');
// We are only changing the chart type, so let's make that a global variable along with the chart object:
var chartType = 'bar';
var myBarChart;
// Global Options:
Chart.defaults.global.defaultFontColor = 'grey';
Chart.defaults.global.defaultFontSize = 16;
var data = {
labels: [ "2012", "2013", "2014", "2015", "2016", "2017",],
datasets: [{
label: "Miljoner ton",
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(0,255,0,0.4)",
borderColor: "green", // The main line color
borderCapStyle: 'square',
pointBorderColor: "white",
pointBackgroundColor: "green",
pointBorderWidth: 1,
pointHoverRadius: 8,
pointHoverBackgroundColor: "yellow",
pointHoverBorderColor: "green",
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: [56.38, 59.3, 61.81, 58.83, 52.32, 66.86],
spanGaps: true,
}]
};
// Notice the scaleLabel at the same level as Ticks
var options = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
title: {
fontSize: 18,
display: true,
text: 'Källa: Globallife.org',
position: 'bottom'
}
};
//Lägg till data
function addData() {
myBarChart.data.labels[6] ="Ekologisk palmolja";
myBarChart.data.datasets[0].data[6] = 14;
myBarChart.update();
}
// We add an init function down here after the chart options are declared.
init();
function init() {
// Chart declaration:
myBarChart = new Chart(ctx, {
type: chartType,
data: data,
options: options
});
}
function button() {
//destroy chart:
myBarChart.destroy();
//change chart type:
this.chartType = (this.chartType == 'bar') ? 'line' : 'bar';
//restart chart:
init();
}
// requested function; removes index 7.
function removeData(e) {
myBarChart.data.labels.splice(7, 1);
myBarChart.data.datasets[0].data.splice(7, 1);
myBarChart.update();
}
function removeData(e) {
myBarChart.data.labels.splice(6, 1);
myBarChart.data.datasets[0].data.splice(6, 1);
myBarChart.update();
}
document.getElementById('remove1').addEventListener('click', removeData);
</script>
Your current code is supplying the same data variable each time you create a chart. Below is an example of switching between two completely different charts by providing different configuration options to the Chart constructor.
let lineConfig = {
type: 'line',
data: {
labels: ['q', 'w', 'e', 'r', 't', 'y'],
datasets: [{
data: [6, 5, 4, 3, 2, 1]
}]
}
},
barConfig = {
type: 'bar',
data: {
labels: ['a', 's', 'd', 'f', 'g', 'h'],
datasets: [{
data: [10, 20, 30, 40, 50, 60]
}]
}
},
activeType = 'bar', // we'll start with a bar chart.
myChart;
function init(config) {
// create a new chart with the supplied config.
myChart = new Chart(document.getElementById('chart'), config);
}
// first init as a bar chart.
init(barConfig);
document.getElementById('switch').addEventListener('click', function(e) {
// every time the button is clicked we destroy the existing chart.
myChart.destroy();
if (activeType == 'bar') {
// chart was a bar, init a new line chart.
activeType = 'line';
init(lineConfig);
return;
}
// chart was a line, init a new bar chart.
activeType = 'bar';
init(barConfig);
});
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="chart"></canvas>
<button id="switch">Switch</button>
Related
I am using charts js version 2.9.4. I am creating a horizontal single-bar chart.
I want to add functionality on legends to Show and hide the single Bar on clicking every legend.
Is it possible to achieve this functionality through chart js or any other chart library?
Thanks!
barChartOptions = {
legend: {
display: true,
position: "bottom",
onHover: function (event, legendItem) {
document.getElementById("mybarChart").style.cursor = "pointer";
},
labels: {
usePointStyle: true,
generateLabels: function (chart) {
var labels = chart.data.labels;
var dataset = chart.data.datasets[0];
var legend = labels.map(function (label, index) {
return {
datasetIndex: 0,
text: label,
fillStyle: dataset.backgroundColor[index],
strokeStyle: dataset.borderColor[index],
lineWidth: 1,
};
});
return legend;
},
},
},
};
yourData = {
labels: [18, 82, 22, 80, 85, 88, 90],
datasets: [
{
data: [1, 2, 3, 4, 10, 12, 15],
barThickness: 20,
backgroundColor: [
"#ff6384",
"#36a2eb",
"#ffce56",
"#4bc0c0",
"#9966ff",
"#9966fe",
"#9955cd",
"#9966ee",
],
borderColor: ["#ff6384", "#36a2eb", "#ffce56", "#4bc0c0", "#9966ff"],
},
],
};
this.chart = new Chart(ctx, {
type: "horizontalBar",
data: yourData,
options: barChartOptions,
});
Thanks
Thanks for the help in advance.I am using doughnut graph of chartjs.In it the percentage value labels are coming on the graph.Is there any way i can hide it.
var category_doughnut_datas = [80,5,5,10];
var category_doughnut__data = {
labels: ["Safe Zone", "Level 1","Level 2","Level 3"],
};
var category_doughnut_options = {
cutoutPercentage: 60,
legend: {
display: false,
position: "top",
paddingBottom: 16,
align: "start",
labels: {
fontColor: "#555555",
fontSize: 20,
boxWidth: 0,
},
},
tooltips: {
displayColors: false,
},
responsive: true,
};
var dough_ctx = document.getElementById("overallStatus").getContext("2d");
if (dough_ctx) {
var myDoughnutChart = new Chart(dough_ctx, {
type: "doughnut",
data: category_doughnut__data,
options: category_doughnut_options,
});
}
Since you dont specify any options to draw it on the chart in your options and its not default chart.js behaviour I expect you defined it as defaults somewhere, in which case you can in your options object in the plugins section specify datalabels: false to stop it from rendering:
Chart.register(ChartDataLabels);
Chart.defaults.plugins.datalabels.color = '#fff';
Chart.defaults.plugins.datalabels.formatter = (value, ctx) => {
let sum = 0;
let dataArr = ctx.chart.data.datasets[0].data;
dataArr.map(data => {
sum += data;
});
let percentage = (value * 100 / sum).toFixed(2) + "%";
return percentage;
};
const options = {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
}]
},
options: {
plugins: {
datalabels: false // Removing this line shows the datalabels again
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.js"></script>
</body>
options.plugins.datalabels: false should be mentioned.
Without it, the value is set to be true by default.
What I want to do it change the Z order of of a line on this chart based on the label attribute. For example, here I would like to make "Label2" plot on top. What I tried to do was mutate the data_all array to put the element I want on top first in the list, though I could not get that work. How can I change the plot order?
So I am creating an array of objects that I can put right into the "data part of chart js like so
data_all=[]
var s1 = {
label: 'Label1',
borderColor: '#00ffff',
fill: false,
data: [
{x: '2021-06-25 11:00:00', y:50.5401942},
{x: '2021-06-25 12:00:00', y:49.9631549},
{x: '2021-06-25 13:00:00', y:50.0555899}]
data_all.push(s1)
var s2 = {
label: 'Label2',
borderColor: '#00ffff',
fill: false,
data: [
{x: '2021-06-25 11:00:00', y:50.5401942},
{x: '2021-06-25 12:00:00', y:49.9631549},
{x: '2021-06-25 13:00:00', y:50.0555899}]
data_all.push(s2)
Then I create a chart by passing data_all in to a chart variable.
var ctx = document.getElementById('plotAll').getContext('2d');
var plotall = new Chart(ctx, {
type: 'line',
data: { datasets: data_all },
options: {
responsive: true,
zoom: {
enabled: true,
mode: 'x'
},
pan: {
enabled: true,
mode: 'xy'
},
scales: {
xAxes: [{
type: 'time'
}]
},
}
});
You can make use of the order property in the dataset, the lower this is, the sooner it will draw that dataset, see example, noramally red line would overlap blue line, now its reversed:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'red',
order: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'blue',
order: 0
}
]
},
options: {}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.0/chart.js"></script>
</body>
I have few charts in my application, created with Chart.js library. I need to export them and include in some kind of reports generated by my application. An example chart code is appended below:
export default {
extends: Line,
mixins: [reactiveProp],
data() {
return {
options: {
maintainAspectRatio: false,
responsive: true,
legend: {
display: true,
position: 'bottom',
},
scales: {
yAxes: [
{
ticks: {
suggestedMin: 0,
callback(tick) {
return `${tick}%`;
},
},
},
],
},
tooltips: {
callbacks: {
label(tooltipItem, data) {
const dataset = data.datasets[tooltipItem.datasetIndex];
const currentValue = dataset.data[tooltipItem.index];
return ` ${dataset.label}: ${currentValue}%`;
},
},
},
animation: {
// eslint-disable-next-line no-unused-vars
onComplete(animation) {
store.commit('myModule/myMutation', this.toBase64Image());
},
},
},
};
},
mounted() {
this.renderChart(this.chartData, this.options);
},
};
As you have noticed, i use onComplete to save the chart in my store. I call the function toBase64Image() there. An image is being saved almost properly, but the background is ignored, so the result is transparent. I would like to have the chart but with the white background after the serialization. Is it possible to achieve it? How can i solve this problem (I've tried to set the background color using the chart styles, but still serialization result is transparent)? Thanks for any help
This behaviour comes because there is nothing drawn on the chart as a background. This can be fixed with a custom inline plugin like so (fillStyle is the color of the background):
plugins: [{
id: 'custom_canvas_background_color',
beforeDraw: (chart) => {
const ctx = chart.canvas.getContext('2d');
ctx.save();
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, chart.canvas.width, chart.canvas.height);
ctx.restore();
}
}]
example:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false
}
}]
}
},
plugins: [{
id: 'custom_canvas_background_color',
beforeDraw: (chart) => {
const ctx = chart.canvas.getContext('2d');
ctx.save();
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, chart.canvas.width, chart.canvas.height);
ctx.restore();
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js" integrity="sha512-hZf9Qhp3rlDJBvAKvmiG+goaaKRZA6LKUO35oK6EsM0/kjPK32Yw7URqrq3Q+Nvbbt8Usss+IekL7CRn83dYmw==" crossorigin="anonymous"></script>
</body>
I have an add data function in my bar-chart but I would like to be able to remove this data with onclick. How do I do this?
var canvas = document.getElementById("barChart");
var ctx = canvas.getContext('2d');
// We are only changing the chart type, so let's make that a global variable along with the chart object:
var chartType = 'bar';
var myBarChart;
// Global Options:
Chart.defaults.global.defaultFontColor = 'grey';
Chart.defaults.global.defaultFontSize = 16;
var data = {
labels: [ "2012", "2013", "2014", "2015", "2016", "2017"],
datasets: [{
label: "Miljoner ton",
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(0,255,0,0.4)",
borderColor: "green", // The main line color
borderCapStyle: 'square',
pointBorderColor: "white",
pointBackgroundColor: "green",
pointBorderWidth: 1,
pointHoverRadius: 8,
pointHoverBackgroundColor: "yellow",
pointHoverBorderColor: "green",
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: [56.38, 59.3, 61.81, 58.83, 52.32, 66.86],
spanGaps: true,
}]
};
// Notice the scaleLabel at the same level as Ticks
var options = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
title: {
fontSize: 18,
display: true,
text: 'Källa: Globallife.org',
position: 'bottom'
}
};
function addData() {
myBarChart.data.labels[7] ="Ekologisk palmolja";
myBarChart.data.datasets[0].data[7] = 14;
myBarChart.update();
}
// We add an init function down here after the chart options are declared.
init();
function init() {
// Chart declaration:
myBarChart = new Chart(ctx, {
type: chartType,
data: data,
options: options
});
}
Below is a working example that demonstrates modifying and updating the chart when clicking a button. Your addData function is a little odd in that it adds data at index 7, but the dataset only has keys 0-5, so this causes an extra blank data point to be inserted at index 6.
In case this isn't what you intended, I added some extra functions (pushData and popData) to show adding and removing from the end of a dataset as that's a quite common requirement (and therefore documented).
// same as original function; inserts or updates index 7.
function addData(e) {
myBarChart.data.labels[7] = "Ekologisk palmolja";
myBarChart.data.datasets[0].data[7] = 14;
myBarChart.update();
}
// requested function; removes index 7.
function removeData(e) {
myBarChart.data.labels.splice(7, 1);
myBarChart.data.datasets[0].data.splice(7, 1);
myBarChart.update();
}
// example of how to add data point to end of dataset.
function pushData(e) {
myBarChart.data.labels.push("Ekologisk palmolja");
myBarChart.data.datasets[0].data.push(14);
myBarChart.update();
}
// example of how to remove data point from end of dataset.
function popData(e) {
myBarChart.data.labels.pop();
myBarChart.data.datasets[0].data.pop();
myBarChart.update();
}
// set listeners on buttons
document.getElementById('add1').addEventListener('click', addData);
document.getElementById('remove1').addEventListener('click', removeData);
document.getElementById('add2').addEventListener('click', pushData);
document.getElementById('remove2').addEventListener('click', popData);
Chart.defaults.global.defaultFontColor = 'grey';
Chart.defaults.global.defaultFontSize = 16;
let myBarChart = new Chart(document.getElementById('chart'), {
type: 'bar',
data: {
labels: ["2012", "2013", "2014", "2015", "2016", "2017"],
datasets: [{
label: "Miljoner ton",
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(0,255,0,0.4)",
borderColor: "green", // The main line color
borderCapStyle: 'square',
pointBorderColor: "white",
pointBackgroundColor: "green",
pointBorderWidth: 1,
pointHoverRadius: 8,
pointHoverBackgroundColor: "yellow",
pointHoverBorderColor: "green",
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: [56.38, 59.3, 61.81, 58.83, 52.32, 66.86],
spanGaps: true
}]
},
options: {
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
title: {
fontSize: 18,
display: true,
text: 'Källa: Globallife.org',
position: 'bottom'
}
}
});
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="chart"></canvas>
<button id="add1">Add index 7</button>
<button id="remove1">Remove index 7</button>
<button id="add2">Add to end</button>
<button id="remove2">Remove from end</button>