How to add unused data background to bar in chart js - javascript

I have the next JS code
let options = {
type: 'bar',
data: data,
options: {
cornerRadius: 30,
maintainAspectRatio: false,
scales: {
xAxes: [{
barPercentage : 0.55,
categoryPercentage: 0.42,
gridLines: {
display: false,
}
}],
yAxes: [{
ticks: {
min: 0,
max: 50,
stepSize: 10,
callback: function(value, index, values) {
return value + "%";
},
fontColor: '#999999',
fontSize: 11,
padding: 15,
fontFamily: 'GothamPro'
}
}],
}
}
}
var siteCosts = document.getElementById('siteCosts').getContext('2d');
var myChart = new Chart(siteCosts, options);
It gives me the next image
https://prntscr.com/t91wzh
And it must look like that https://prntscr.com/t91xsf
The question is next - how to add this grey unused data to bar via Chart.js?

Since I don't know about your data, I have prepared a custom data. Look carefully that I have taken all the data 95 in the second dataset because the highest value of the first dataset is 95. I think you can solve this in this way.
var ctx = document.getElementById('myChart').getContext("2d");
ctx.canvas.width = 300;
ctx.canvas.height = 200;
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["A", "B", "C", "D", "E"],
datasets: [{
backgroundColor: 'rgb(54, 195, 110)',
borderColor: 'rgba(255, 255, 255, 0.5)',
borderWidth: 0,
data: [95, 75, 80, 55, 85]
}, {
backgroundColor: '#948E8D',
borderColor: 'rgba(255, 255, 255, 0.5)',
borderWidth: 0,
data: [95, 95, 95, 95, 95]
}],
},
options: {
cornerRadius: 30,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
barPercentage: 0.55,
categoryPercentage: 0.42,
gridLines: {
display: false,
},
stacked: true
}],
yAxes: [{
ticks: {
min: 0,
max: 95,
stepSize: 10,
callback: function (value, index, values) {
return value + "%";
},
fontColor: '#999999',
fontSize: 11,
padding: 15,
fontFamily: 'GothamPro'
},
stacked: true
}],
}
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js" type="text/javascript"></script>
</head>
<body>
<canvas id="myChart"></canvas>
</body>
</html>

Related

Changing Chartjs Horizontal Scrollling Direction

I would like to change the direction of scrolling on a horizontal scrollable bar chart in such way scrolling start from right to left (RTL). I'm not sure if it is supported or not. in case, it is not, then is there a way to programmatically scroll to the far right of the chart upon loading to achieve the desired outcome.
const chartsoptions = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5", "6",],
datasets: [{
label: 'OFF',
data: [1, 2, 3, 4, 5, 6],
backgroundColor: [ 'rgba(255, 99, 132, 0.4)', ],
borderColor: [ 'rgb(255, 99, 132)', ],
borderWidth: 1
},{
label: 'On',
data: [6, 5, 4, 3, 2, 1],
backgroundColor: [ 'rgba(75, 192, 192, 0.4)', ],
borderColor: ['rgb(75, 192, 192)', ],
borderWidth: 1
}]
},
options: {
plugins: {
legend: {
display: true,
labels: {
font: {
size: 20,
weight: "bold",
},
}
},
datalabels: {
anchor: 'center',
clamp: true,
display: true,
textAlign: 'center',
borderRadius: 3,
color: "black",
clip: true,
font: {
size: 20,
weight: "bold",
},
},
zoom: {
zoom: { wheel: { enabled: false, }, mode: 'x', },
pan: { enabled: true, mode: 'x', },
limits: { x: { minRange: 3 }, },
}
},
scales: {
x: { ticks: { font: { size: 20, weight: "bold" }, } },
y: { ticks: { font: { size: 20, weight: "bold" }, } },
}
}
}
const ctx = document.getElementById('dailyonoff').getContext('2d');
document.getElementById('dailyonoff').style.backgroundColor = "white";
const chart = new Chart(ctx, chartsoptions);
setTimeout(() => {
chart.zoom(2);
chart.pan({
x: Number.MAX_SAFE_INTEGER
}, undefined, 'default');
}, 10)
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js" integrity="sha256-+8RZJua0aEWg+QVVKg4LEzEEm/8RFez5Tb4JBNiV5xA=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.1.1/chartjs-plugin-zoom.js"></script>
</head>
<body>
<canvas id="dailyonoff" class="onoff" width="300" height="200" ></canvas>
</body>
</html>
I found the solution to navigate (pan) to the end of the graph. just replace:
MAX_SAFE_INTEGER
with:
MIN_SAFE_INTEGER

chart.js cuts data points to half

I have a chart showing website calls the last 7 days. There it is:
Here is the initialization:
varwebsitecalls_chart = new Chart(websitecalls_chartel, {
type: 'line',
data: {
labels: ["Sa", "So", "Mo", "Di", "Mi", "Do", "Fr"],
datasets: [{
label: 'Websitecalls',
data: [0, 0, 0, 0, 0, 0, 0],
borderWidth: 2,
borderColor: '#00000',
backgroundColor: '#ffff',
pointStyle: 'circle',
pointRadius: 7,
cubicInterpolationMode: 'monotone',
tension: 0.4,
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
},
scales: {
x: {
grid: {
display: false,
}
},
y: {
min: 0,
ticks: {
precision: 0,
font: {
family: 'Montserrat',
},
},
grid: {
borderDash: [5, 5],
}
},
}
},
});
Problem:
The Problem is that the chart cuts of the circles when the data is 0 because I set min to 0. I have to set min to 0 because negative websitecalls can not exist. If I do not set it -1 will be displayed. Is there a way to fix this designtechnical issue?
Thanks in advance,
Filip.
No idea why, but defining y.beginAtZero: true instead of y.min: 0 will solve the problem.
Please take a look at your amended and runnable code and see how it works.
new Chart('websitecalls_chartel', {
type: 'line',
data: {
labels: ["Sa", "So", "Mo", "Di", "Mi", "Do", "Fr"],
datasets: [{
label: 'Websitecalls',
data: [0, 0, 0, 0, 0, 0, 0],
borderWidth: 2,
borderColor: '#00000',
backgroundColor: '#ffff',
pointStyle: 'circle',
pointRadius: 7,
cubicInterpolationMode: 'monotone',
tension: 0.4,
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
},
scales: {
x: {
grid: {
display: false,
}
},
y: {
beginAtZero: true,
ticks: {
precision: 0,
font: {
family: 'Montserrat',
},
},
grid: {
borderDash: [5, 5],
}
},
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
<canvas id="websitecalls_chartel" height="80"></canvas>
Chart.js documentation states...
beginAtZero: if true, scale will include 0 if it is not already included.
min: user defined minimum number for the scale, overrides minimum value from data.

Chartjs bar min, max and avarage value

Hi I have a chart with chartjs, which inserts between min, max, average values, with a bar type chart.
So far, everything is fine, the values are entered, what I want to do is that the bars of the graph are positioned starting from their min on the y axis up to the maximum on the y axis, I do not want the bar to start from the value 0.
dataset = {
labels: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'],
datasets: [{
label: 'min',
borderWidth: 4,
borderColor: "#ef4931",
backgroundColor: "#ef4931",
borderJoinStyle: 'miter',
pointHitRadius: 10,
data: data[1],
fill: false,
},
{
label: 'avg',
borderWidth: 4,
borderColor: "#ef4931",
backgroundColor: "#ef4931",
borderJoinStyle: 'miter',
pointHitRadius: 10,
data: data[0],
fill: "-1",
},
{
label: 'max',
borderWidth: 4,
borderColor: "#ef4931",
backgroundColor: "#ef4931",
borderJoinStyle: 'miter',
pointHitRadius: 10,
data: data[2],
fill: "-1",
}
]
};
options = {
legend: {
display: false,
},
title: {
display: true,
position: 'bottom',
fontSize: 14
},
tooltips: {
mode: 'index',
intersect: false,
titleFontStyle: "bold",
titleFontColor: "rgba(255, 255, 255, 1)",
bodyFontStyle: "normal",
bodyFontColor: "rgba(255, 255, 255, 1)",
backgroundColor: "rgba(102, 102, 102, 1)",
borderWidth: 1,
bodySpacing: 5,
xPadding: 15,
yPadding: 15,
displayColors: false,
callbacks: {
title: function(item, data) {
var title = "";
title += item[0].xLabel;
return title;
}
}
},
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
stacked: true,
barThickness: 10,
}],
yAxes: [{
stacked: true,
display: true,
scaleLabel: {
display: true,
fontSize: 14,
fontStyle: "bold",
},
ticks: {
callback: function(value, index, values) {
return parseInt(value) + " bpm";
},
}
}]
},
animation: {
duration: 1000,
easing: "easeInOutQuad"
}
};
myChart.config.data = dataset;
myChart.options = options;
myChart.config.type = "bar";
myChart.update();
in your y axes config you can add the prop suggestedMin or min between the stacked and display prop. With this the scale will start at that number, here you can put in the value of the lowest bar.
SuggestedMin will go lower if there is a bar with a lower value, if you use min if will use that as a final so if you have a bar with a lower value it wont get shown.
You can combine "floating bars" and "stacked bar chart". See https://codepen.io/fantasyzer/pen/KKaqgoM for an example. Note that the data of each bar is given as an array [Ybegin,Yend]. If you set stackable to false for the y scale the values are to be given as absolute:
datasets: [
{
data: [
[10,12],
[20,25],
[15,25],
[25,28],
...
Ref:
https://www.chartjs.org/docs/latest/samples/bar/floating.html, https://www.chartjs.org/docs/latest/samples/bar/stacked.html

how can i use chart.js to create a chart that has one time series line and one linear line on it at the same time?

I want to draw a reference line in the time series chart. I tried to use two x axis and two y axis so I have like two graphs in one. the one would show time scale line and the other one would show linear line (reference line).
image example of what I want it to look like :
I tried in fiddle but its like the two X axis are connected and not scaling separately:
var data = {
labels: [],
datasets: [{
fill: 'none',
label: 'signal1',
backgroundColor: 'rgba(75,192,192,0.4)',
pointRadius: 5,
pointHoverRadius: 7,
borderColor: 'rgba(75,192,192,1)',
borderWidth: 1,
lineTension: 0,
xAxisID: 'xAxis1',
yAxisID: 'yAxis1',
data: [{
x: '2016-07-17',
y: 44
},
{
x: '2016-07-19',
y: 50
},
{
x: '2016-07-22',
y: 84
},
],
}, {
fill: 'none',
label: 'signal2',
lineTension: 0,
xAxisID: 'xAxis2',
yAxisID: 'yAxis2',
data: [{
x: 0,
y: 55
},
{
x: 1,
y: 55
},
]
}],
};
var option = {
scales: {
yAxes: [{
id: 'yAxis1',
offset: true,
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: true,
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 15,
drawBorder: true,
},
ticks: {
beginAtZero: false,
padding: 5,
fontSize: 12,
fontColor: '#222222',
},
}, {
id: 'yAxis2',
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: false,
drawBorder: false,
},
ticks: {
beginAtZero: false,
},
}],
xAxes: [{
id: 'xAxis1',
offset: true,
bounds: 'data',
type: 'time',
distribution: 'linear',
time: {
unit: 'day',
displayFormats: {
day: 'D.M.YYYY',
},
},
gridLines: {
display: true,
color: 'rgba(151, 151, 151, 0.2)',
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 5,
drawBorder: true,
},
ticks: {
source: 'auto',
autoSkip: true,
autoSkipPadding: 30,
maxRotation: 0,
padding: 2,
fontSize: 12,
fontColor: '#222222',
},
}, {
id: 'xAxis2',
type:"linear",
gridLines: {
display: false,
drawBorder: false,
},
}]
}
};
https://jsfiddle.net/2gyk9v5e/15/
This can be done with the Plugin Core API. The API offers different hooks that may be used for executing custom code. In your case, you can use the afterDraw hook to draw the desired lines directly on the canvas using CanvasRenderingContext2D.
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
chart.data.datasets[0].refLines.forEach(r => {
var y = yAxis.getPixelForValue(r.y);
ctx.strokeStyle = r.color;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
});
ctx.restore();
}
}],
Above code assumes that the reference lines are defined inside your dataset through the following definition.
refLines: [
{ y: 45, color: '#0be059' },
{ y: 49, color: '#fc3503' }
]
Please take a look at your amended code and see how it works.
new Chart('canvas', {
type: 'line',
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
chart.data.datasets[0].refLines.forEach(r => {
var y = yAxis.getPixelForValue(r.y);
ctx.strokeStyle = r.color;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
datasets: [{
fill: false,
label: 'signal1',
backgroundColor: 'rgba(75,192,192,0.4)',
pointRadius: 5,
pointHoverRadius: 7,
borderColor: 'rgba(75,192,192,1)',
borderWidth: 1,
lineTension: 0,
data: [
{ x: '2016-07-14', y: 44 },
{ x: '2016-07-15', y: 52 },
{ x: '2016-07-16', y: 45 },
{ x: '2016-07-17', y: 47 },
{ x: '2016-07-18', y: 35 },
{ x: '2016-07-19', y: 46 },
{ x: '2016-07-20', y: 50 },
{ x: '2016-07-21', y: 44 }
],
refLines: [
{ y: 45, color: '#0be059' },
{ y: 49, color: '#fc3503' }
]
}]
},
options: {
scales: {
yAxes: [{
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: false,
drawBorder: false
}
}],
xAxes: [{
offset: true,
bounds: 'data',
type: 'time',
time: {
unit: 'day',
displayFormats: {
day: 'D.M.YYYY',
}
},
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 5,
drawBorder: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="canvas" height="80"></canvas>

Chart.js: Strange Visual appearing in top left corner?

There appears a strange Visual in the top left corner of the chart image within the canvas, that looks like a string that is cut off by the canvas.
Image of visual appearing
This remains no matter the canvas size or browser I use to open the HTML-file.
I also cannot recall when this Visual first started appearing and I have tried to fix it by removing parts of the code to see when it starts to appear but currently to no avail.
If someone can find a fix for this issue I'd appreciate your help.
My current Code:
Javascript Code:
const offset = 27;
var myChart = new Chart(document.getElementById('Chart'), {
type: 'bar',
plugins: [{
afterUpdate: function(chart) {
var dataset = chart.config.data.datasets[1];
for (var i = 0; i < dataset._meta[0].data.length; i++) {
var model = dataset._meta[0].data[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
var dataset = chart.config.data.datasets[2];
for (var i = 0; i < dataset._meta[0].data.length; i++) {
var model = dataset._meta[0].data[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
},
}],
data: {
labels: ['Black', 'Red','Cyan',
'Blue', 'Orange', 'Purple',
'Green','Grey', 'Other'],
datasets: [{
label: 'Result now',
data: [18.4, 34.9, 6.1, 9.8,15.3,3.6,4.3,5.7,1.9],
backgroundColor: [
'#000000',
'#fa0000',
'#09fae0',
'#0011ff',
'#ff7300',
'#d400db',
'#00ff09',
'#666666',
'#bababa'
],
categoryPercentage: 1.0,
barPercentage: 0.45,
xAxisID: "Now",
datalabels: {
color: 'rgba(0,0,0,1)',
anchor: 'end',
align: 'top'
},
},
{
//Previous Election | Current Result highter
label: 'Last Result',
data: [, 20.1, , , 8.9,,3.4, ,1.5],
backgroundColor: [
'rgba(0, 0, 0, 0.4)',
'rgba(250, 0, 0, 0.4)',
'rgba(9, 250, 224, 0.4)',
'rgba(0, 17, 255, 0.4)',
'rgba(255, 115, 0, 0.4)',
'rgba(212, 0, 219, 0.4)',
'rgba(0, 255, 9, 0.4)',
'rgba(102, 102, 102, 0.4)',
'rgba(186, 186, 186, 0.4)'
],
categoryPercentage: 1.0,
barPercentage: 0.3,
xAxisID: "Then",
datalabels: {
color: 'rgba(0,0,0,0.7)',
anchor: 'end',
align: '-50'
},
},
{
//Previous Election | Current Bars lower
label: 'Last Result',
data: [25.7, ,16.4 ,16.1 , ,4.7,, ,],
backgroundColor: [
'rgba(0, 0, 0, 0.4)',
'rgba(250, 0, 0, 0.4)',
'rgba(9, 250, 224, 0.4)',
'rgba(0, 17, 255, 0.4)',
'rgba(255, 115, 0, 0.4)',
'rgba(212, 0, 219, 0.4)',
'rgba(0, 255, 9, 0.4)',
'rgba(102, 102, 102, 0.4)',
'rgba(186, 186, 186, 0.4)'
],
categoryPercentage: 1.0,
barPercentage: 0.3,
xAxisID: "Then_2",
datalabels: {
color: 'rgba(0,0,0,0.7)',
anchor: 'end',
align: 'end'
}
}]
},
options: {
responsive: false,
legend: {
display: false,
onClick: false,
},
scales: {
xAxes: [{
id: "Now",
gridLines: {
display: false
},
ticks: {
fontColor: 'rgba(0,0,0,1)'
}
},
{
id: "Then",
offset: true,
display: false
},
{
id: "Then_2",
offset: true,
display: false
},
],
yAxes: [{
ticks: {
min: 0,
max: 50,
stepSize: 10,
fontColor: 'rgba(0,0,0,1)',
callback: function(value, index, values) {
return value + '%';
}
},
gridLines: {
display: true,
color: 'rgba(0,0,0,0.3)',
},
scaleLabel :{
display: true,
labelString: "Vote Share",
fontColor: 'rgba(0,0,0,1)'
}
}]
},
plugins: {
datalabels: {
formatter: function(value, context) {
return value + '%';
},
}
},
}
});
Html Code:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title> Chart Test </title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<br>
<script src="chartjs/dist/Chart.bundle.min.js"></script>
<script src="chartjs/dist/chartjs-plugin-datalabels.js"></script>
<div id="Result">
<h3>Results</h3>
<canvas id="Chart" width="1055px" height="705px"></canvas>
<script type="text/javascript" src="js/Chart_1.js"></script>
</div>
</body>
<html>
CSS Code:
#Result{
float: center;
width: 1095px;
height: 805px;
text-align: center;
}
I know it's a bit late, had the same issue and i found a fix for mine maybe it could work for you too.
The problem was my data, having empty data instead of "0" makes chartjs returning NaN, that was the cut text displayed on the top left corner.
In my opinion, you should replace :
data: [, 20.1, , , 8.9,,3.4, ,1.5],
by
data: [0, 20.1, 0, 0, 8.9,0,3.4,0,1.5],
Hope it solves yours ! :)

Categories