How to remove transparency from images downloaded in Chart.js - javascript

How can I remove opacity from downloaded images using the toBase64Image() function in Chart.js?
If possible, save to JPG instead of PNG.
This is the code:
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
},
animation: {
onComplete: function() {
image = graficoConsumo.toBase64Image();
}
}
}
});
document.getElementById('btn-download-chart').onclick = function() {
// Trigger the download
var a = document.createElement('a');
a.href = image;
a.download = 'myChart.png';
a.click();
}

No by default canvases dont have a background so it will always be transparent. To fix this you can write a small custom plugin that draws a white background before chart.js draws its things on it:
Chart.register({
id: 'customBackground',
beforeDraw: (chart, args, opts) => {
const ctx = chart.canvas.getContext('2d');
ctx.save();
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, chart.width, chart.height);
ctx.restore();
}
})
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'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'pink'
}
]
},
options: {},
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
body {
background-color: black;
}
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.2/chart.js"></script>
</body>

Related

Vertical Bar Chart not displaying Correctly

Vertical bar chart:
I want to achieve this vertical bar chart image in the link above but the result of my code is displaying a normal bar chart. Here is a snippet of the code I'm using to generate the chart:
<template name="VerticalCharts">
<div class="profile-user-box">
<canvas id="myCharts"></canvas>
</div>
</template>
Template.VerticalCharts.onRendered(function() {
var ctx = document.getElementById('myCharts').getContext('2d');
var myCharts = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Bar Chart'
}
}
},
});
});
What you have is a vertical bar chart, if you want horizontal bars you need to set the indexAxis to 'y' in your options object like so:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
indexAxis: 'y'
}
}
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.5.1/chart.js"></script>
</body>

How to convert a bar chart into a triangle shaped chart using Chart JS?

How to convert a bar chart into a triangle shaped chart using Chart JS ?
For eg: Sample Bar Chart : How to convert it into triangles instead of bars ?
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
You can use a scatter chart and define individual datasets for each value.
Please take a look at your amended code and see how it works.
const labels = ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'];
const data = [12, 19, 3, 5, 2, 3];
const colors = ['255, 99, 132', '54, 162, 235', '255, 206, 86', '75, 192, 192', '153, 102, 255', '255, 159, 64'];
const datasets = labels.map((l, i) => ({
label: l,
data: [{ x: i + 1 - 0.45, y: 0 }, { x: i + 1, y: data[i] }, { x: i + 1 + 0.45, y: 0 }],
fill: true,
backgroundColor: 'rgba(' + colors[i] + ', 0.2)',
borderColor: 'rgb(' + colors[i] + ')',
showLine: true,
borderWidth: 1,
lineTension: 0,
pointRadius: 0,
pointHitRadius: 0
}));
new Chart('myChart', {
type: 'scatter',
data: {
datasets: datasets
},
options: {
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: labels.length + 1,
ticks: {
callback: (v, i) => labels[i - 1]
},
grid: {
display: false
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js"></script>
<canvas id="myChart" height="110"></canvas>
You will have to implement your own custom chart type to do this since it's not possible by default, you can read here in the documentation how to implement your own chart type: https://www.chartjs.org/docs/master/developers/charts.html

How can I add the sum of all values as chart title for a doughnut chart in Chart.Js?

My example currently looks like this:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
rotation: 1 * Math.PI,
circumference: 1 * Math.PI,
title: {
display: true,
text: 'Custom Chart Title',
position: 'bottom'
}
}
});
Now I want to display the sum of the values from data: [12, 19, 3, 5, 2, 3] as title of the chart (So, in this case the title would be 44). Some example fiddle is here: https://jsfiddle.net/ktq8mb0z/. How can I achieve that in Chart.Js?
You can user reduce function
dataset[0].data.reduce((x,y)=>x+y)
or You can also use this
dataset.reduce((t,d) => t + d.data.reduce((a,b) => a+b),0)
var ctx = document.getElementById("myChart");
var dataset=[{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}];
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: dataset
},
options: {
rotation: 1 * Math.PI,
circumference: 1 * Math.PI,
title: {
display: true,
text: 'Custom Chart Title and Sum is : '+dataset.reduce((t,d) => t + d.data.reduce((a,b) => a+b),0),
position: 'bottom'
}
}
});
.snippet-code .snippet-result .snippet-result-code{
min-height:640px!important;
height:640px!important;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<canvas id="myChart" width="400" height="400"></canvas>
Since ChartJS version 3.x.x:
half-doughnut is configured with degrees
title is part of 'plugins'
Therefore, use this configuration:
options: {
rotation: -90,
circumference: 180,
plugins: {
title: {
display: true,
text: 'Total: ' + data.reduce((total, dataPoint) => total + dataPoint, 0),
position: 'bottom',
},
},
}

ChartJS Only Show Large Font Size for a Specific Tick

I am attempting to emphasize a specific value on the X-Axis if it meets a specific condition.
For example, in my codepen I want to only change the font size of the 'blue' bar. Is this even possible with Chart.js?
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}],
xAxes: [{
ticks: {
//only show large font size for 'Blue'
fontSize: 16
}
}]
}
}
});
Chartjs doesn't have a public api to do this but you can modify internal _ticks on beforeDraw and make the label "Blue" as major: true then that label will be drawn using the major styling in tick configuration options.
Also use this with caution since it relies on internal implementation and thus might break in future releases (very unlikely to happen but just saying).
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}],
xAxes: [{
ticks: {
fontSize: 16,
major: {
fontSize: 20
}
}
}]
}
},
plugins: [{
beforeDraw: function({ chart }, options) {
chart.boxes
.find(box => box.id === "x-axis-0")
._ticks
.find(tick => tick.label === "Blue")
.major = true;
}
}]
});
<canvas id="myChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
PS: Just in case someone is wondering how I know this internal implementation I searched fillText in chartjs github source code and console.log(myChart) xD
Looks like it's not possible according to their docs. You can only do something like uppercase needed label with callback function
xAxes: [{
ticks: {
fontSize: 16,
callback: v => v === 'Blue' ? v.toUpperCase() : v
}
}]
For chartjs 3.0 and higher, it can be done by using scriptable-options. Include it like this into your options for ticks:
options: {
scales: {
x: {
ticks: {
font: {
size: (c) => {
if (c.index==1){
return 20 // at tick label with idx one set fontsize 20
}
else {
return 12 // for all other tick labels set fontsize 12
}
},
},
},
},
},
},

Add shadow Chart.js

I'm using the last version of chart.js and I want to add a shadow to each bar
Here's an example of code
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)'],
borderColor: ['rgba(255,99,132,1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)'],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>
This will work for the line chart.
[Edited...]
Chart.types.Line.extend({
name: "LineAlt",
initialize: function () {
Chart.types.Line.prototype.initialize.apply(this, arguments);
var ctx = this.chart.ctx;
var originalStroke = ctx.stroke;
ctx.stroke = function () {
ctx.save();
ctx.shadowColor = '#000';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 8;
ctx.shadowOffsetY = 8;
originalStroke.apply(this, arguments)
ctx.restore();
}
}
});
var data = {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
fillColor: "rgba(255, 99, 132, 0.2)",
strokeColor: "rgba(54, 162, 235, 0.2)",
pointColor: "rgba(255, 206, 86, 0.2)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(75, 192, 192, 0.2)",
data: [12, 19, 3, 5, 2, 3]
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
var canvas = new Chart(ctx).LineAlt(data, {
datasetFill: false
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<canvas id="myChart" width="600" height="300"></canvas>
Appreciate if useful
Based on this answer, I created a runnable code snippet that illustrates how to create bars with shadows.
const dataset = [40, 80, 50, 60, 70];
const offset = 8;
Chart.pluginService.register({
afterUpdate: function(chart) {
var metaData = chart.getDatasetMeta(0).data;
for (var i = 0; i < metaData.length; i++) {
var model = metaData[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
}
});
var data = {
labels: ["A", "B", "C", "D", "E"],
datasets: [{
backgroundColor: [
'rgba(255, 99, 132)',
'rgba(255, 206, 86)',
'rgba(54, 162, 235)',
'rgba(75, 192, 192)',
'rgba(153, 102, 255)'
],
borderWidth: 1,
data: dataset,
xAxisID: "bar-x-axis1",
categoryPercentage: 0.5,
barPercentage: 0.5,
},
{
backgroundColor: 'rgba(0, 0, 0, 0.2)',
data: dataset.map(v => v + offset),
xAxisID: "bar-x-axis2",
categoryPercentage: 0.5,
barPercentage: 0.5
}
]
};
var options = {
legend: {
display: false
},
tooltips: {
enabled: false
},
scales: {
xAxes: [
{
id: "bar-x-axis2"
},
{
id: "bar-x-axis1",
offset: true,
display: false
}
],
yAxes: [{
id: "bar-y-axis1",
ticks: {
beginAtZero: true,
stepSize: 50
}
}]
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="60"></canvas>

Categories