Related
I am using chart.js from a frontend react application. I need to create a plot with chart.js so that I can attach it to a powerpoint slide with pptxgen. This image does not have to be rendered visually, I just need to create it when the user requests to generate the ppt.
Chart needs a context, so I created a canvas element to act as such, then tried to render and export the base64 image that I would then proceed to feed into pptxgen:
let ctx = document.createElement("canvas")
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart: Chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
} )
chart.render()
console.log(chart.toBase64Image())
But all I obtain is "data:;" which looks to be an empty image.
Do you know how to make it render?
The only way to render a chart without you specifically adding it to the dom is by making use of the offscreen-canvas as explained here in the documentation of chart.js:
https://www.chartjs.org/docs/3.7.1/general/performance.html#parallel-rendering-with-web-workers-chromium-only
Downside is that the offscreen canvas API is only available in chromium based browsers.
Other approach you can take is by adding the canvas to the dom, let chart.js render to it, get the base64 representation and then remove the canvas directly after that like so:
let ctx = document.createElement("canvas")
document.documentElement.appendChild(ctx)
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart = new Chart(ctx, {
type: "bar",
data: {
labels: ['a', 'b', 'c', 'd', 'e', 'f', ' g'],
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
})
const base64 = chart.toBase64Image();
ctx.remove();
console.log(base64)
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
its not possible to render without attaching canvas to dom, but you can hide it and it will work as expected.
const chartEl = document.createElement("canvas");
const ctx = chartEl.getContext("2d");
chartEl.setAttribute("width", "400");
chartEl.setAttribute("height", "400");
chartEl.style.display = "none";
document.body.append(chartEl);
let chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [
{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}
]
},
options: {
scales: {}
}
});
chart.render();
console.log(chart.toBase64Image());
chartEl.remove();
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
I am using chart.js from a frontend react application. I need to create a plot with chart.js so that I can attach it to a powerpoint slide with pptxgen. This image does not have to be rendered visually, I just need to create it when the user requests to generate the ppt.
Chart needs a context, so I created a canvas element to act as such, then tried to render and export the base64 image that I would then proceed to feed into pptxgen:
let ctx = document.createElement("canvas")
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart: Chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
} )
chart.render()
console.log(chart.toBase64Image())
But all I obtain is "data:;" which looks to be an empty image.
Do you know how to make it render?
The only way to render a chart without you specifically adding it to the dom is by making use of the offscreen-canvas as explained here in the documentation of chart.js:
https://www.chartjs.org/docs/3.7.1/general/performance.html#parallel-rendering-with-web-workers-chromium-only
Downside is that the offscreen canvas API is only available in chromium based browsers.
Other approach you can take is by adding the canvas to the dom, let chart.js render to it, get the base64 representation and then remove the canvas directly after that like so:
let ctx = document.createElement("canvas")
document.documentElement.appendChild(ctx)
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart = new Chart(ctx, {
type: "bar",
data: {
labels: ['a', 'b', 'c', 'd', 'e', 'f', ' g'],
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
})
const base64 = chart.toBase64Image();
ctx.remove();
console.log(base64)
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
its not possible to render without attaching canvas to dom, but you can hide it and it will work as expected.
const chartEl = document.createElement("canvas");
const ctx = chartEl.getContext("2d");
chartEl.setAttribute("width", "400");
chartEl.setAttribute("height", "400");
chartEl.style.display = "none";
document.body.append(chartEl);
let chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [
{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}
]
},
options: {
scales: {}
}
});
chart.render();
console.log(chart.toBase64Image());
chartEl.remove();
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>
I´m trying to build a stacked bar chart with a marker on top.
how it should look like
.
So I tried to build a bar chart and combine it with a line chart, but that doesn´t work well.
my result so far
.
Is there a way to get a similar result ?
var chartData = {
labels: ["Zukauf", "Produktion"],
datasets: [
{
label: "offene TP",
data: [102, 55],
backgroundColor: "rgba(15,173,25,1)",
hoverBackgroundColor: "rgba(15,173,25,1)"
},{
label: "erledigte TP",
data: [256, 55],
backgroundColor: "rgba(220,111,18,1)",
hoverBackgroundColor: "rgba(220,111,18,1)"
},{
type: "line",
label: "Plan",
data: [425],
backgroundColor: "rgba(255,255,255,0)",
borderColor: "rgba(0,0,0,0.4)",
borderWidth: 2,
hoverBackgroundColor: "rgba(12,128,133,1)"
}
]
};
After few confusing researches in the chartjs documentation I found the perfect solution.
solution picture
var chartData = {
labels: ["Zukauf", "Produktion"],
datasets: [
{
label: "offene TP",
data: [102, 55],
backgroundColor: "rgba(220,111,18,1)",
hoverBackgroundColor: "rgba(220,111,18,1)"
},{
label: "erledigte TP",
data: [256, 55],
backgroundColor: "rgba(15,173,25,1)",
hoverBackgroundColor: "rgba(15,173,25,1)"
},{
label: "Plan",
data: [425, 500],
borderColor: "rgba(0,0,0,1)",
//important settings
//set the width of the line ( or point )
pointRadius: 50,
// don´t show line betrween points
showLine: false,
//change points of line chart to line style ( little bit confusin why it´s named point anyway )
pointStyle: 'line',
//chart type
type: "line",
}
]
};
Only need to change the 'pointStyle' to 'line', the 'pointRadius' for the width of the line and disable 'showLine'.