Chart.js not height responsive - javascript

I have issues to get the chart.js line chart to be responsive on the height as well as the width.
See example what it should be working like:
http://www.chartjs.org/samples/latest/charts/line/basic.html
Here is my code:
var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
var lineChartData = {
labels : ['January','February','March','April','May','June','July'],
datasets : [
{
label: 'My First dataset',
labelColor : '#fff',
fontColor : '#fff' ,
backgroundColor : 'rgba(220,220,220,0.2)',
borderColor : 'rgba(220,220,220,1)',
pointBackgroundColor : 'rgba(220,220,220,1)',
pointBorderColor : '#fff',
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
}
]
}
var options = {
maintainAspectRatio: false,
legend: {
display: false,
},
scales: {
xAxes: [{
gridLines: {
display: false,
color: '#03A5C5',
lineWidth: 8,
},
ticks: {
fontColor: "white",
},
}],
yAxes: [{
gridLines: {
display: false,
color: '#03A5C5',
lineWidth: 8,
},
ticks: {
fontColor: "white",
beginAtZero: true,
}
}]
}
};
var ctx = document.getElementById('canvas-1');
var chart = new Chart(ctx, {
responsive: true,
type: 'line',
data: lineChartData,
options: options
});

Create Class
.chart-container {
position: relative;
margin: auto;
height: 80vh;
width: 80vw;
}
Create Div With class chart-container and place canvas tag inside it.
<div class="chart-container">
<canvas id="canvas"></canvas>
</div>
Chart options, use property maintainAspectRatio set to false:
options: {
maintainAspectRatio: false,
responsive: true,
...
}

As from Docs for Chart.js it's recommended to wrap canvas into container div and change width/height of the container. But basically it's changing either by given width or height.
Found a more flexible custom solution from lannymcnie that can be used for any canvas responsiveness:
var stage = new createjs.Stage("canvas");
var c = new createjs.Shape();
c.graphics.f("#f00").dc(0,0,50); // Drawn a 100x100 circle from the center
var t = new createjs.Text("Resize the browser/frame to redraw", "24px Arial bold", "#000");
t.x = t.y = 20;
stage.addChild(c, t);
window.addEventListener("resize", handleResize);
function handleResize() {
var w = window.innerWidth-2; // -2 accounts for the border
var h = window.innerHeight-2;
stage.canvas.width = w;
stage.canvas.height = h;
//
var ratio = 100/100; // 100 is the width and height of the circle content.
var windowRatio = w/h;
var scale = w/100;
if (windowRatio > ratio) {
scale = h/100;
}
// Scale up to fit width or height
c.scaleX= c.scaleY = scale;
// Center the shape
c.x = w / 2;
c.y = h / 2;
stage.update();
}
handleResize(); // First draw
html, body {
padding: 0; margin: 0;
overflow:hidden;
}
canvas {
border: 1px solid #f00;
}
<script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
<canvas id="canvas" width="800" height="600"></canvas>

You can have it responsive and set a different aspect ratio. My issue was that the chart tend to be squeezed on mobile device taking barely no height.
To remedy, with chart.js 3.2.1, I am using the AspectRatio option:
options: {
aspectRatio: 1,
}
This way the chart is square and stay square, you can play with this number usually between 0.5 to 2 to find a ratio that suits you on both displays.

Related

Chartjs small offset on top

HTML
<body>
<div style = "width:100%; height:100%; display:flex; align-items:center; justify-content:center;">
<div style = "width:300px; height:300px; display:flex; align-items:center; justify-content:center; background-color:blue">
<canvas id="canvas" style = "width:300px; height:300px; background-color:green"></canvas>
</div>
</div>
</body>
JAVASCRIPT
<script>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var radius = 0.5;
var options =
{
title:
{
display:false,
},
legend:
{
display:false
},
tooltip:
{
enabled:false
},
animation:
{
duration: 0
}
}
var data =
{
datasets:
[
{
data: [50, 50],
backgroundColor: ["blue", "red"],
borderWidth: 0
}
]
}
var chart =
new Chart(context,
{
type: "doughnut",
cutout: 100 * radius,
responsive: true,
data: data,
options: options
});
</script>
FIDDLE
https://jsfiddle.net/t5a41rdj/
As per title, somehow this chart has a little offset on top which I can't seem to be able to get rid of, despite having disabled legend and title.
Anything obvious I am missing?
This is because you did not disable the legend, title or tooltip. If you hover your chart you can see the tooltip is still working, title is hidden by default. Why the legend does not show I dont really know, should still show 1 item with undefined as text. But if you disable it in the correct space with is the plugins namespace you see your extra padding goes away.
Also cutout and responsive have to be configured in the options not in the root of new Chart:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var radius = 0.5;
var options = {
plugins: {
legend: {
display: false
},
tooltip: {
enabled: false
}
},
animation: {
duration: 0
},
cutout: 100 * radius,
responsive: true,
}
var data = {
datasets: [{
data: [50, 50],
backgroundColor: ["blue", "red"],
borderWidth: 0,
}]
}
var chart =
new Chart(context, {
type: "doughnut",
data: data,
options: options
});
<body>
<div style="width:100%; height:100%; display:flex; align-items:center; justify-content:center;">
<div style="width:300px; height:300px; display:flex; align-items:center; justify-content:center; background-color:blue">
<canvas id="canvas" style="width:300px; height:300px; background-color:green"></canvas>
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

ChartJS xAxis label position

I have a ChartJS that display the label as slanted when you resize the window to smaller size.
What I want to do is to lower the X-labels down a bit vertically so they are not as close to the base of the graph if possible.
After googling around, it looks like I can disable the tick display for x-Axis and use the option's animation to do this manually. I tried to implement this in the following fiddle.
animation: {
duration: 1,
onComplete: function() {
var chartInstance = this.chart;
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
var label = bar._model.label;
var xOffset = bar._model.x;
var yOffset = bar._model.y;
ctx.fillText(label, xOffset, 420);
});
});
}
},
However, I can't get the label to scale properly when I resize the window. Can you help?
Chart.js implements a padding property in the ticks object for this:
Padding between the tick label and the axis. When set on a vertical axis, this applies in the horizontal (X) direction. When set on a horizontal axis, this applies in the vertical (Y) direction.
Here's a working example with the x-axis labels offset 20px down from the line:
new Chart(document.getElementById("chart"), {
type: "bar",
data: {
labels: ["Blue", "Red", "Green", "Orange", "Purple"],
datasets: [{
data: [0, 1, 2, 3, 4]
}]
},
options: {
maintainAspectRatio: false,
scales: {
xAxes: [{
ticks: {
padding: 20
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<div style="height:200px;width:200px">
<canvas id="chart"></canvas>
</div>

Style dash in highchart graphic

I'm trying to change the line style of a chart, but I'm not getting it. I'm
looking to change the black line in the middle of the chart, to the style "DASH"
I already put the "dashStyle: 'dash'" in several places, but without success.
The example is the one of the highcharts
I'm trying to change the line style of a chart, but I'm not getting
it.
It is not possible because what you call line is actually an SVG rectangle element. That's why it can't be dashed.
However, you can achieve what you want by adding some custom logic and using Highcharts.SVGRenderer. Simply remove default rectangle graphic of each series point and render several rectangles with breaks to create a dashed line. Check the code and demo posted below.
Code:
Highcharts.setOptions({
chart: {
inverted: true,
marginLeft: 135,
type: 'bullet',
events: {
render: function() {
var chart = this,
point = chart.series[0].points[0],
width = point.shapeArgs.height,
height = point.shapeArgs.width,
x = chart.plotLeft,
xEnd = x + width,
y = chart.plotTop + point.shapeArgs.x,
dashWidth = 15,
dashBreakWidth = 5,
dashColor = '#000',
dashElem,
dashAmount,
realDashBreakWidth;
if (chart.dashedColl) {
chart.dashedColl.forEach(function(oldDashElem) {
oldDashElem.destroy();
});
}
point.graphic.element.remove();
chart.dashedColl = [];
dashAmount = Math.floor(width / (dashWidth + dashBreakWidth));
realDashBreakWidth = (width - dashAmount * dashWidth) / (dashAmount - 1);
while (x < xEnd) {
dashElem = chart.renderer.rect(x, y, dashWidth, height)
.attr({
fill: dashColor
})
.add()
.toFront();
chart.dashedColl.push(dashElem);
x += dashWidth + realDashBreakWidth;
}
}
}
},
title: {
text: null
},
legend: {
enabled: false
},
yAxis: {
gridLineWidth: 0
},
plotOptions: {
series: {
pointPadding: 0.25,
borderWidth: 0,
color: 'red',
targetOptions: {
width: '200%'
}
}
},
credits: {
enabled: false
},
exporting: {
enabled: false
}
});
Demo:
https://jsfiddle.net/BlackLabel/7azfso1r/
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#rect
https://api.highcharts.com/class-reference/Highcharts.Point#remove
https://api.highcharts.com/highcharts/chart.events.render

Label is not showing in ChartJS

I'm using ChartJS for my implementation of charts, but I notice that one of my graph's label is hidden. It is not showing its label above the bar. I've added a screenshot below for the comparison of two different bar graphs. The left graph shows the label even if it is on the very top but the other one is not showing. Please see my screenshot and code below.
function createChart(context, type, bgColor, bdColor, labels, actualData, options = {}){
new Chart(context, {
type: type,
data: {
labels: labels,
datasets: [{
label: "Actual",
backgroundColor: bgColor,
borderColor: bdColor,
data: actualData,
}]
},
options: options
});
}
function getOptions(displayLegend = true){
return {
events: false,
showTooltips: false,
legend: {
display: displayLegend
},
animation: {
duration: 0,
onComplete: function(){
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseLine = 'bottom';
ctx.fillStyle = '#0b7707';
this.data.datasets.forEach(function(dataset){
console.log(dataset);
for(var i = 0; i < dataset.data.length; i++){
for(var key in dataset._meta){
var model = dataset._meta[key].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y - 13);
}
}
});
}
}
};
}
I solved this problem by adding an empty title to the chart, so it will create space above the chart and show labels above the bar
options: {
title: {
display: true,
text: ' '
},
....
This looks like a clear case of the datalabels going out of the canvas since the bar takes height dynamically as per the data values. You can set the max y-tick setting to solve this. Here is the jsfiddle -> https://jsfiddle.net/Luaf2tm4/5979/
Hope it helps!
var canvas = document.getElementById('myChart');
var data = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
label: "My First dataset",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 2,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [500, 2000, 800, 600, 950, 890],
}]
};
function getOptions(displayLegend = false) {
return {
events: false,
showTooltips: false,
legend: {
display: displayLegend
},
scales: {
yAxes: [{
display: true,
stacked: true,
ticks: {
stepSize: 200,
min: 0, // minimum value
max: 2200 // maximum value, you can either hard code if you know your datainput, else computer the value through some logic i.e taking the max value from the dataset and adding some extra value to it.
}
}]
},
animation: {
duration: 0,
onComplete: function() {
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseLine = 'bottom';
ctx.fillStyle = '#0b7707';
this.data.datasets.forEach(function(dataset) {
console.log(dataset);
for (var i = 0; i < dataset.data.length; i++) {
for (var key in dataset._meta) {
var model = dataset._meta[key].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y - 10);
}
}
});
}
}
};
}
var myBarChart = Chart.Bar(canvas, {
data: data,
options: getOptions()
});

Chart area background color chartjs

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.

Categories