Chart area background color chartjs - javascript

I have problem with chart js, i want to coloring chart area like image above
I try to find configuration from charJs Docs , but nothing matched.
its possible or not to change chart area background color?
if possible anyone can help me?
Html
<canvas id="barChart" width="600" height="300"></canvas>
Javascript
var ctx = document.getElementById("barChart");
var barChart = new Chart(ctx,{
type: 'bar',
data: {
labels:["Label1","Label2","Label3","Label4"],
borderColor : "#fffff",
datasets: [
{
data: ["2","3","1","4"],
borderColor : "#fff",
borderWidth : "3",
hoverBorderColor : "#000",
backgroundColor: [
"#f38b4a",
"#56d798",
"#ff8397",
"#6970d5"
],
hoverBackgroundColor: [
"#f38b4a",
"#56d798",
"#ff8397",
"#6970d5"
]
}]
},
options: {
scales: {
yAxes: [{
ticks:{
min : 0,
stepSize : 1,
fontColor : "#000",
fontSize : 14
},
gridLines:{
color: "#000",
lineWidth:2,
zeroLineColor :"#000",
zeroLineWidth : 2
},
stacked: true
}],
xAxes: [{
ticks:{
fontColor : "#000",
fontSize : 14
},
gridLines:{
color: "#fff",
lineWidth:2
}
}]
},
responsive:false
}
});
Here's my current code jsFiddle
so everyone can try for find solution.
thanks for your help.

There is no built-in method to change background color, but you can use CSS. JSFiddle.
ctx.style.backgroundColor = 'rgba(255,0,0,255)';
EDIT
If you want to fill exact area of chart and no whole div, you can write your own chart.js plugin. Try it on JSFiddle.
Chart.pluginService.register({
beforeDraw: function (chart, easing) {
if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
var ctx = chart.chart.ctx;
var chartArea = chart.chartArea;
ctx.save();
ctx.fillStyle = chart.config.options.chartArea.backgroundColor;
ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
ctx.restore();
}
}
});
var config = {
type: 'bar',
data: {
labels:["Label1","Label2","Label3","Label4"],
borderColor : "#fffff",
datasets: [
{
data: ["2","3","1","4"],
borderColor : "#fff",
borderWidth : "3",
hoverBorderColor : "#000",
backgroundColor: [
"#f38b4a",
"#56d798",
"#ff8397",
"#6970d5"
],
hoverBackgroundColor: [
"#f38b4a",
"#56d798",
"#ff8397",
"#6970d5"
]
}]
},
options: {
scales: {
yAxes: [{
ticks:{
min : 0,
stepSize : 1,
fontColor : "#000",
fontSize : 14
},
gridLines:{
color: "#000",
lineWidth:2,
zeroLineColor :"#000",
zeroLineWidth : 2
},
stacked: true
}],
xAxes: [{
ticks:{
fontColor : "#000",
fontSize : 14
},
gridLines:{
color: "#fff",
lineWidth:2
}
}]
},
responsive:false,
chartArea: {
backgroundColor: 'rgba(251, 85, 85, 0.4)'
}
}
};
var ctx = document.getElementById("barChart").getContext("2d");
new Chart(ctx, config);

The canvas background is transparent by definition, like any element, so you just need to define the background-color in your canvas, for example, in your case you will need this CSS:
JSFiddle
canvas#barChart {
background-color: #f00;
}
or HTML inline, to clarify the idea:
<canvas id="barChart" width="600" height="300" style="background-color: #f00;"></canvas>

This works on latest chartjs
const custom_canvas_background_color = {
id: 'custom_canvas_background_color',
beforeDraw: (chart, args, options) => {
const {
ctx,
chartArea: { top, right, bottom, left, width, height },
scales: { x, y },
} = chart;
ctx.save();
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = '#E5E5E5';
ctx.fillRect(left, top, width, height);
ctx.restore();
},
};
Then add as plugin
plugins: [custom_canvas_background_color]

If you want to set a colour for the whole Canvas (and not just the plotting area), you can do it like this:
Chart.pluginService.register({
beforeDraw: ({ config: { options }, ctx }) => {
if (options.chartArea?.backgroundColor) {
ctx.save();
ctx.fillStyle = options.chartArea.backgroundColor;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.restore();
}
}
});
const chart = new Chart(document.getElementById('chart'), {
options: {
chartArea: {
backgroundColor: 'rgba(255, 255, 255, 1)'
}
}
});
This will be applied to the PNG when using chart.toBase64Image()

You can achieve this by implementing this Chartjs plugin plugin / example. The plugin allows you to enhance your chart. For example zoom in or pan on to your chart. But also change the background color. Using setBackgroundColor(color); //updates the background color of the chart.

Related

How to get radar chart coordinates using getValueForDistanceFromCenter with Chart.js?

I am experimenting with Chart.js to build radar charts. I mastered the basics (see basic chart below), but I would like to use the x y coordinates of the graph to place texts directly on the canvas.
After some digging, I found out that it is not possible to use getValueForPixel or getPixelForTick in a radar chart. See this github issue. In the connecting thread, a new method getValueForDistanceFromCenter is introduced.
As I understand it, it would be possible to calculate the distance from the center with this method, and use it to get coordinates. I searched the Chart.js documentation and other sites, but cannot find any code examples or information on how to implement this.
Can somebody point me in the right direction how to implement the method in the code?
var data = {
labels: ["Ball Skills", "Shooting", "Physical"],
datasets: [{
label: [`ikke`, `jij`],
backgroundColor: "rgba(38,120,255,0.2)",
borderColor: "rgba(38,120,255, 1)",
data: [90, 90, 90]
}]
};
var options = {
responsive: true,
tooltips: false,
title: {
text: 'Basic example',
display: true,
position: `bottom`,
},
scale: {
angleLines: {
display: true
},
ticks: {
suggestedMin: 0,
suggestedMax: 100,
stepSize: 25,
maxTicksLimit: 11,
display: false,
}
},
legend: {
labels: {
padding: 10,
fontSize: 14,
lineHeight: 30,
},
},
};
var myChart = new Chart(document.getElementById("chart"), {
type: 'radar',
data: data,
options: options
});
The radialLinear scale (in version 2.9.4 that I have seen your are using version 2) there is the method getValueForDistanceFromCenter(value) to get the distance from center but there is another method getPointPositionForValue(index, value) which can provide you the point at a specif index of your data.
To use them and to draw what you want on chart using those points, you need to implement a plugin.
In the below snippet, I'm drawing a rect between the points at a specific value.
const ctx = document.getElementById("myChart");
const data = {
labels: ["Ball Skills", "Shooting", "Physical"],
datasets: [{
label: [`ikke`, `jij`],
backgroundColor: "rgba(38,120,255,0.2)",
borderColor: "rgba(38,120,255, 1)",
data: [50, 50, 50]
}]
};
const options = {
responsive: true,
tooltips: false,
title: {
text: 'Basic example',
display: true,
position: `bottom`,
},
scale: {
angleLines: {
display: true
},
ticks: {
suggestedMin: 0,
suggestedMax: 100,
stepSize: 25,
maxTicksLimit: 11,
display: false,
}
},
legend: {
labels: {
padding: 10,
fontSize: 14,
lineHeight: 30,
},
},
};
const plugin = {
id: 'getDistance',
afterDraw(chart) {
const c = chart.ctx;
const rScale = chart.scale;
c.save();
chart.data.datasets[0].data.forEach(function(item, index) {
const point = rScale.getPointPositionForValue(0.5 + index, 50);
c.beginPath();
c.fillStyle = 'red';
c.fillRect(point.x - 5, point.y - 5, 10, 10);
c.fill();
});
c.restore();
}
};
const myChart = new Chart(ctx, {
type: 'radar',
plugins: [plugin],
data: data,
options: options
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>

How to plot a single value with line in line chart graph using charts.js?

I need to plot a single value in line chart. Currently i am using charts.JS library for line graph purpose.
The data will be varied some times i'll get the single data inside the data set at that time i need to plot the single value with line in the line chart.
I tried with the charts.js annotation plugin but it wasn't met my requirements. which is like it wis overlapping the plotted point in the graph area.
CODE WHICH I HAD TRIED
createLineChart() {
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: "line",
data: {
labels:[],
datasets: [
{
fill: false,
backgroundColor: "#0168FF",
borderColor: "#0168FF",
pointBackgroundColor: "white", // wite point fill
pointBorderWidth: 1, // point border width
lineTension: 0,
pointBorderColor: "blue",
pointRadius: 4,
},
],
},
options: {
scales: {
yAxes: [
{
ticks: {
padding: 20,
beginAtZero: true,
min: 0,
stepSize: 100,
},
gridLines: {
drawBorder: false,
},
},
],
xAxes: [
{
// offset: true,
ticks: {
display: false,
//beginAtZero: true,
min: 0,
},
gridLines: {
zeroLineColor: "transparent",
drawBorder: false,
display: false,
},
//offset:true,
},
],
legend: {
display: false,
},
tooltips: {
enabled: false,
},
},
drawTime: "afterDraw", // (default)
} as ChartOptions,
// plugins: [ChartAnnotation]
},
});
}
To generate dynamic data and plot in the graph area.
generateRandomDataSet(size) {
let yaxisArr = [];
let xaxisArr = [];
let random_data:any = this.getRandomData(size)
let maxYTickVal = Math.max.apply(Math, random_data.map((val) => {return val.yaxis}));
let maxVal = Math.ceil((maxYTickVal+1) / 10) * 10
for(let data of random_data) {
yaxisArr.push(data.yaxis)
xaxisArr.push(data.xaxis)
}
console.log("X-Axis array values : "+xaxisArr)
console.log("Y-Axis array values : "+yaxisArr)
this.lineChart.data.datasets[0].data = yaxisArr
this.lineChart.config.data.labels = []
this.lineChart.config.data.labels = xaxisArr
this.lineChart.config.options.scales.yAxes[0].ticks.max =maxVal
this.lineChart.config.options.scales.yAxes[0].ticks.stepSize = maxVal/2
this.lineChart.update()
}
getRandomData(arraySize) {
let data = []
for(var i=1; i<=arraySize; i++) {
let number = Math.floor(Math.random() * 200) + 1
data.push({'xaxis':i,'yaxis':number})
}
return data
}
with the above code i am getting like
what i need to have
You can define an animation.onComplete function as follows to draw the line in case a single data value is present.
animation: {
onComplete: e => {
var ctx = chart.chart.ctx;
var data = chart.config.data.datasets[0].data;
if (data[0] == null) {
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var y = yAxis.getPixelForValue(data[1]);
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.strokeStyle = 'blue'
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
ctx.restore();
}
}
},
This function expects the data array to be of format [null, <value>, null] in case a single value is present, otherwise it will be hard to horizontally center the data point (see this answer). It's up to you to change the generateRandomDataSet() function in a way that it provides such data.
Please have a look at your changed code below.
const chart = new Chart('line-chart', {
type: "line",
data: {
labels: ['', 'A', ''],
datasets: [{
data: [null, 120, null],
fill: false,
backgroundColor: "#0168FF",
borderColor: "#0168FF",
pointBackgroundColor: "white",
pointBorderWidth: 1,
lineTension: 0,
pointBorderColor: "blue",
pointRadius: 4,
}],
},
options: {
legend: {
display: false
},
tooltips: {
enabled: false
},
animation: {
onComplete: e => {
var ctx = chart.chart.ctx;
var data = chart.config.data.datasets[0].data;
if (data[0] == null) {
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var y = yAxis.getPixelForValue(data[1]);
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.strokeStyle = 'blue'
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
ctx.restore();
}
}
},
scales: {
yAxes: [{
ticks: {
padding: 20,
min: 0,
stepSize: 100
},
gridLines: {
drawBorder: false
}
}],
xAxes: [{
ticks: {
display: false
},
gridLines: {
zeroLineColor: "transparent",
drawBorder: false,
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="line-chart" height="80"></canvas>

Chart.js - Add gradient to bar chart

I am looking to build a chart like this
But I am not able to give the gradient colors in the y-scale for the bar chart. This is the codesandbox URL.
The gradient direction (Vertically in your case) not related directly to chart.js, but to HTML canvas createLinearGradient() Method.
createLinearGradient JavaScript syntax:
context.createLinearGradient(x0,y0,x1,y1);
https://www.w3schools.com/tags/canvas_createlineargradient.asp
Example of top to bottom "vertically" gradient from w3schools:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var my_gradient = ctx.createLinearGradient(0, 0, 0, 170);
my_gradient.addColorStop(0, "black");
my_gradient.addColorStop(1, "white");
ctx.fillStyle = my_gradient;
ctx.fillRect(20, 20, 150, 100);
<div>Top to bottom</div>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
"One gradient"
Docs:
An alternative option is to pass a CanvasPattern or CanvasGradient
object instead of a string colour. https://www.chartjs.org/docs/latest/general/colors.html#patterns-and-gradients
Same as one solid color but passing CanvasGradient object:
var bar_ctx = document.getElementById('chart').getContext('2d');
var background_1 = bar_ctx.createLinearGradient(0, 0, 0, 600);
background_1.addColorStop(0, 'red');
background_1.addColorStop(1, 'blue');
And set background_1 under data
/* data */
var data = {
labels: ["Africa", "Asia", "Europe", "America"],
datasets: [{
/* data */
label: "Population (millions)",
backgroundColor: background_1,
data: [40,60,80, 100]
}]
};
"multiple colors for bars"
Use multiple gradients objects inside backgroundColor (object1 for item-1 and so on).
backgroundColor: [background_1, background_2, background_3, background_4],
** My code is not DRY (The best idea her is to create gradient objects by some loop throw array of data). By purpose i keep this example "simple".
var bar_ctx = document.getElementById('chart').getContext('2d');
var background_1 = bar_ctx.createLinearGradient(0, 0, 0, 600);
background_1.addColorStop(0, 'red');
background_1.addColorStop(1, 'blue');
var background_2 = bar_ctx.createLinearGradient(0, 0, 0, 600);
background_2.addColorStop(0, 'green');
background_2.addColorStop(1, 'orange');
var background_3 = bar_ctx.createLinearGradient(0, 0, 0, 600);
background_3.addColorStop(0, 'orange');
background_3.addColorStop(1, 'purple');
var background_4 = bar_ctx.createLinearGradient(0, 0, 0, 600);
background_4.addColorStop(0, 'green');
background_4.addColorStop(1, 'violet');
/* data */
var data = {
labels: ["Africa", "Asia", "Europe", "America"],
datasets: [{
/* data */
label: "Population (millions)",
backgroundColor: [background_1, background_2, background_3, background_4],
data: [40,60,80, 100]
}]
};
var options = {
responsive: true,
title: {
text: 'multiple colors for bars',
display: true
},
scales: {
xAxes: [{
stacked: true,
ticks: {
},
}],
yAxes: [{
stacked: true,
}]
}
};
var myChart = new Chart(document.getElementById("chart"), {
type: 'bar',
data: data,
options: options
});
<canvas id="chart" width="800" height="600"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
Try to click one of the jsfiddle there, then change the chart type to 'bar'. You'll see it will work.
Yes they are all the same color, because on their example they are only using one gradient. You can create multiple gradient with different color and apply it seperately since you are using multiple rgba already, you can change it and apply specific gradient to your bar. My english is not that good i hope you get my point.

chart.js - horizontalBar stacked chart with xaxis as dates

I am looking to create a bar chart but have had a hell of a time trying to find what I need through chart.js 2.1
Goal is to have a chart that looks like this:
sample image
So far I have been unsuccessful getting the xAxis to reflect dates.
Here's the story:
yAxis are vendor groups that have stacking due dates (the dates may/may not match up with another vendor group). Each stack has a numeric value as well, but this does not affect the layout of the chart, just an overlay of data.
xAxis are all the due dates, starting with the current date and moving on.
Any assistance or jfiddle examples would be EXTREMELY helpful!
Here's what I have today: https://jsfiddle.net/npk3xdb0/
HTML:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#latest/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<canvas id="bar-chart-horizontal" width="200" height="50"></canvas>
JAVASCRIPT:
new Chart(document.getElementById("bar-chart-horizontal"), {
type: "horizontalBar",
data: {
labels: ['V1','V2','V3'],
datasets: [{ data: [50, 60, 75], backgroundColor: "#8C453E"},{ data: [50, 70, 85], backgroundColor: "#684796"},{ data: [50, 53, 111], backgroundColor: "#427780"},{ data: [19, , ], backgroundColor: "#599647"}]
},
options: {
tooltips: { enabled: false },
hover :{ animationDuration:0 },
scales: {
xAxes: [{
ticks: { beginAtZero:true, fontFamily: "'Open Sans Bold', sans-serif", fontSize:11 },
scaleLabel:{ display:false },
gridLines: { },
stacked: true
}],
yAxes: [{
gridLines: { display:false, color: "#fff", zeroLineColor: "#fff", zeroLineWidth: 0 },
ticks: { fontFamily: "'Open Sans Bold', sans-serif", fontSize:11 },
stacked: true
}]
},
legend:{ display:false },
animation: {
onComplete: function () {
var chartInstance = this.chart;
var ctx = chartInstance.ctx;
ctx.textAlign = "right";
ctx.font = "9px Open Sans";
ctx.fillStyle = "#fff";
Chart.helpers.each(this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
Chart.helpers.each(meta.data.forEach(function (bar, index) {
data = dataset.data[index];
//if(i==0){
// ctx.fillText(data, 20, bar._model.y+4);
//} else {
ctx.fillText(data, bar._model.x-3, bar._model.y+4);
//}
}),this)
}),this);
}
},
pointLabelFontFamily : "Quadon Extra Bold",
scaleFontFamily : "Quadon Extra Bold",
}
});

Chart.js - How to offset bars from ZeroLine

I've spent hours already trying to figure out how to offset the horizontal bars from the zero line on X-Axis so it doesn't overlap when the width of the line is bigger than 1.
Appreciate all the help.
Example is here on CodePen (hope it will show up): https://codepen.io/RomanKl/pen/mzmegG
var barOptions = {
tooltips: {
enabled: false
},
hover :{
animationDuration:0
},
scales: {
xAxes: [{
ticks: {
beginAtZero:true,
min: 0,
max: 10000,
fontFamily: "'Open Sans Bold', sans-serif",
fontSize:12,
callback: function(value, index, values) {
return Math.round(value/1000) + 'k';
}
},
scaleLabel:{
display:false
},
gridLines: {
color: ['#000', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef'],
lineWidth: [4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
zeroLineWidth: 4,
zeroLineColor: '#000',
},
}],
yAxes: [{
gridLines: {
display: false,
},
ticks: {
fontFamily: "'Open Sans Bold', sans-serif",
fontSize:14,
},
}]
},
legend:{
display:false
},
animation: {
onComplete: function () {
var chartInstance = this.chart;
var ctx = chartInstance.ctx;
ctx.textAlign = "left";
ctx.font = "1.6rem Open Sans";
ctx.fillStyle = "#fff";
Chart.helpers.each(this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
Chart.helpers.each(meta.data.forEach(function (bar, index) {
data = dataset.data[index];
data = data.toFixed(0).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
if(i==0){
ctx.fillText(data, 80, bar._model.y+4);
} else {
ctx.fillText(data, bar._model.x-25, bar._model.y+4);
}
}),this)
}),this);
}
},
};
var ctx = document.getElementById("Chart1");
var myChart = new Chart(ctx, {
type: 'horizontalBar',
borderSkipped: 'bottom',
data: {
labels: ["Aug.'17", "Aug.'18"],
datasets: [{
data: [6336, 6892],
backgroundColor: "rgba(63,103,126,1)",
hoverBackgroundColor: "rgba(50,90,100,1)"
}]
},
options: barOptions,
});
So I've brutally hacked it in the end. I've tried adding a border and then skip it everywhere except the start where I would set the colour to transparent but guess what? Border doesn't show up at the start. It's a requested feature not yet implemented in chart.js as of this posting.
In the end I've used a diabolical solution of using two stacked datasets while setting the first one via data to the desired offset and then setting backgroundColor to transparent and shifting data labels to the left via plugin.
you can see the result in the codepen link posted in the question.

Categories