Charts.js sets canvas width/height to 0 and displays nothing
Asked Answered
C

4

23

I am trying to use Charts.js to make the default line plot that they show in their example dynamically and put it in a div that I pop up on a user click. My code is like this:

this.chartCanvas = document.createElement('canvas');
this.div.appendChild(this.chartCanvas);
this.chartCanvas.style.height = '480px';
this.chartCanvas.style.width = '900px';
this.chartCanvas.width = 900;
this.chartCanvas.height = 480;
this.ctx = this.chartCanvas.getContext('2d');

this.chart = new Chart(this.ctx).Line(data);

When I make the call to "new Chart" my canvas height and width are set to 0 as I can see in the inspector. When I comment out this call my canvas has the proper width/height and displays as one would expect. If I manually change the canvas height/width in the inspector my chart still doesn't display.

My "data" object is just what I cut and paste directly from their line chart example here: http://www.chartjs.org/docs/#line-chart-example-usage

Can anyone provide some insight on where I might be going wrong, I am completely new to the library.

Clemens answered 18/9, 2015 at 21:34 Comment(0)
C
15

It appears that the issue is that the canvas and all its parent nodes cannot have display none at the time the chart call is made so if you are using a chart in a popup you need to show the popup, construct the chart and then hide the popup.

As this Fiddle shows, if you try and construct a chart in a hidden div and then show it on a timeout it does not work.

If you instead show the div, make the chart and then hide the div, it does work.

http://jsfiddle.net/bjudheoq/4/

//This will break it
//this.div.style.display = 'none';
this.chart = new Chart(this.ctx).Line(data);
this.div.style.display = 'none';

The above fiddle works, but if you uncomment line 40 it does not.

Clemens answered 18/9, 2015 at 23:57 Comment(0)
P
19

In my case the canvas needed to be wrapped inside an element with the CSS display: block;

Plastered answered 8/12, 2017 at 9:14 Comment(5)
This worked for me in my angular5 app. Just put a <div> around the canvas.Loney
Worked for me inside a hidden tab in a vue appArbil
Any explanation for why this is the case?Mcdonnell
@Mcdonnell because otherwise the code which checks the parent element for the width and height calculation will get a 0 value. Just set on some element: display: unset and console log out the elements height with JS: $0.clientHeight ($0 is the element) and you will see: 0. (I tried it right now just with your comment) => For elements the display value is initially set (div => block, span => inline-block), for others like Angular new / custom ones not.Plastered
Thanks @SteveHanov It worked for me after adding div around the canvas in ionic angular.Grimaldo
C
15

It appears that the issue is that the canvas and all its parent nodes cannot have display none at the time the chart call is made so if you are using a chart in a popup you need to show the popup, construct the chart and then hide the popup.

As this Fiddle shows, if you try and construct a chart in a hidden div and then show it on a timeout it does not work.

If you instead show the div, make the chart and then hide the div, it does work.

http://jsfiddle.net/bjudheoq/4/

//This will break it
//this.div.style.display = 'none';
this.chart = new Chart(this.ctx).Line(data);
this.div.style.display = 'none';

The above fiddle works, but if you uncomment line 40 it does not.

Clemens answered 18/9, 2015 at 23:57 Comment(0)
D
2

I found an option:

options: {
    responsive: false,
    ...

This makes conflict with default true. I don't know it works properly at the moment. Ofcourse set the width and height to the canvas and its parent.

Desirable answered 28/11, 2021 at 8:21 Comment(0)
D
0

Your code works, with the exception of a typo. This line...

this.chartCanvs.style.width = '900px';

...should be this:

this.chartCanvas.style.width = '900px';
//            ^ your code is missing this 'a'

And here's a JS Fiddle with that typo fixed: http://jsfiddle.net/dun5dhne/

Also, I strongly recommend opening your browser's developer console when you run into problems. This kind of thing is easy to catch in the console.

Doubler answered 18/9, 2015 at 23:29 Comment(4)
my code actually doesn't have the typo, I put that into stack overflow, but given that your fiddle works I ought to be able to figure it ought from that, ty. There are no console errors, I always keep it open.Clemens
I wonder if it's a problem with your this.div.appendChild(this.chartCanvas) call. In your code, are you sure this.div is a reference to a valid <div> that exists in the DOM?Doubler
Yes, it is. I believe I figured out the issue. If you look at this fiddle: jsfiddle.net/bjudheoq/2 you can see that if you set the divs display to 'none' and then reveal it on a 1 second timeout, the div displays (a bit red rectangle) but the chart is blank. If you comment out the this.div.style.display = 'none'; on line 27 then everything works. Since I am trying to show the chart in a popup that is initially hidden this may be my issue.Clemens
I confirmed this is the issue in my code as well. If I don't create the chart until after the popup div that holds it is visible then everything works. ChartJS must use the innerHeight or innerWidth of the container div or something of that nature.Clemens

© 2022 - 2024 — McMap. All rights reserved.