apertureless / vue-chartjs

📊 Vue.js wrapper for Chart.js
https://vue-chartjs.org
MIT License
5.55k stars 837 forks source link

Chart is not rendered when maintainAspectRatio is set to false and chart container is hidden #235

Closed canfone closed 7 years ago

canfone commented 7 years ago

Hi,

First of all, thanks for creating this package as vue wrapper for chartjs. I have a use case where my chart is hidden initially then when the user will click the button, the chart will show.

Before I added the option maintainAspectRatio: false, everything works fine. The chart will be rendered even it is being rendered in a hidden div. But once I added the option mentioned above, only charts that are visible is rendered. The hidden charts are not rendered.

Expected Behavior

Chart should still render in a hidden div with maintainAspectRatio: false

Actual Behavior

Chart is not rendered in a hidden div with maintainAspectRatio: false

Environment

UPDATE

I found out that the bug when the container is hidden is the canvas height is 0. It seems that the height props was not properly propagated if container is hidden upon rendering.

apertureless commented 7 years ago

Can you provide a codepen for reproduction? This could be standard chart.js behaviour tho. It also depends on how you hide your container. With a v-if or v-show.

apertureless commented 7 years ago

closed due to inactivity

goranmitev commented 6 years ago

Hi, I have the same problem. I'm using bootstrap-vue and the tabs component and here is a codepen with the problem https://codepen.io/goranmitev/pen/NXXEpy

When you put a chart in an inactive tab, the chart is not rendered if maintainAspectRatio: false

apertureless commented 6 years ago

Well thats a common thing with chart.js. I guess the tabs are working with display: none and if the component gets mounted the parent div has a height and width of 0. Because of the display: none .

Thats why you can't see anything. Chart.js is grabbing the height and width and applying it to the canvas. You can try to pass a fix height or remove the responsive: true.

Because responsive: true will get the parent element width and height and apply it to the canvas. So it grows and shrinks while resizing. So responsive: true is causing the real issue.

maintainAspectRatio: true however fixes this because

Maintain the original canvas aspect ratio (width / height) when resizing.

So I guess setting the tab to display: block triggers the resize listener and recalculating the canvas size.

jowilhnson commented 6 years ago

Have the same problem with vuetify tabs, though in my case it is not displaying the charts because the height gets set to 0. Setting responsive: false or maintainAspectRatio: true make a mess of things, and fixed dimensions are a last resort.

Interestingly, if I switch from having this.renderChart() in mounted() to beforeMount() it allots the correct amount of space for the chart. Which of course doesn't render because of cannot read property getContext of undefined, but I thought it was interesting that it manages to allot correct dimensions at that point in the lifecycle.

JColl88 commented 5 years ago

Has anyone been able to find a workaround for this? I hit it a few months ago in Chrome for an application I was co-developing and found this thread to be useful; when I realised that it was the canvas height that was being set to zero I could set the height after instantiating the chart and then the chart rendered fine. Unfortunately this fix doesn't work in Firefox. I've attached a pseudo-code version of the widget to show the structure of the file in case this helps to identify the problem. Changing the chart option 'maintainAspectRatio' to true means the chart is rendered, but at the wrong aspect ratio.

chartbug.txt

apertureless commented 5 years ago

Well, there is no real workaround. Like explained, if the canvas has a display: none on it, it's height is equal to 0.

You could maybe try to add a MutationObserver to the element and check if the display: none is gone and then call this.renderChart() which should force a re-render.

Otherwise don't use v-show, use v-if with proper unmounting / remounting.

Ivwc commented 5 years ago

resize add in settimeout ex:

setTimeout(() => {
    this.$refs.radar.echarts.resize();
    this.$refs.pie.echarts.resize();            
}, 300);

i think when we switch tab ,then chart can not find parent width or height so i wait when i switch tab it is work

desaikalpesh34 commented 4 years ago

Just Defining parent height it will work like charm.

<div class="renderChart" style="height:350px;">
   <canvas id="pieChart"> </canvas>
</div>

Now show/hide renderChart will work.

strife-cloud commented 2 years ago

Another solution is to adapt the radius so it can fit the screensize so you don't need maintainAspectRatio = true that is causing the problem, you have an event called "onresize".

For my case, on web screen radius = 300, on mobile screen radius = 150 for example.