amCharts doesn't display chart for initially-hidden divs

匿名 (未验证) 提交于 2019-12-03 09:06:55

问题:

I am using amCharts (which uses behind the scenes) to render some charts as SVG; and have noticed that if the SVG is rendered in an initially-invisible div, the browser does not immediately render the image when the div becomes visible. If I modify the display however, e.g. by resizing the browser or Ctrl-mousewheel zooming, the SVG image is then rendered as expected when the page is redrawn.

The exact method of div visibility switching is via Bootstrap's tabbed navbar.

I admit to not being very experienced with SVG - is this an issue with the browsers' rendering, or amCharts' SVG markup, or am I required to explicitly call some sort of repaint method when I can tell the visibility of an SVG has changed?

Here's a jsFiddle which illustrates the problem; if you switch to Section 2 (in Chrome, Firefox) the chart isn't visible initially. Resizing the display causes it to appear.

回答1:

I've found the reason for both the initial behaviour and the workaround - and it's all amCharts specific (nothing to do with SVG per se) so I'm rephrasing the title accordingly.

What happens is that when amCharts creates the SVG, it needs to (or at least, decides to) define the width and height in absolute terms. These are based on the size of the target div, obtained via the offsetWidth and offsetHeight properties.

The inactive tab has the display: none property set, and as a result this part of the DOM is not even rendered, so returns zero for both size properties. This ultimately leads to amCharts creating a 0x0 SVG chart when chart.write is called for the hidden div.

Resizing fixes things because each chart registers a listener to the onresize window event, which calls the chart's handleResize method. This forces a recalculation of the width and height based on the div's new (current) dimensions.


So in conclusion I think there are two alternative ways to handle this:

  • Call chart.write for a chart when and only when its tab becomes visible.
  • Call each chart's handleResize method when the tabs change.

(The first option avoids the initial hit of rendering an invisible chart, but then does a full redraw every time the tabs are changed. The latter takes a hit up-front but is likely quicker thereafter. For bonus marks, the best solution would be to render each chart exactly once between each resize, the first time it becomes visible, but that's a lot more complex as it would involve interfering with the default event listeners, amongst other things.)

Update: There's further complications with rendering an invisible chart; in particular, I found issues with the height calculations not taking into account the space required by the domain axis and so stretching the chart out of its div. This wasn't fixed by calling handleResize - calling measureMargins beforehand looked like it should work but didn't. (There's probably another method one could call after this to make it work such as resetMargins but at this point it started to feel very flaky...)

As such I don't think it's practical to render a chart for the first time on a non-visible div, so I went with some combination of the bullets above. I listen for when a chart's tab becomes visible for the first time and then call chart.write for the appropriate chart object - and whenever the tabs change, all previously-rendered charts are told to handle the resize.



回答2:

* Edited *

Here is a updated fiddle. The Canvas will only be rendered once the tab is shown. I store the chartdiv ids in an array and check whether there are in it or not.

* Edited *

The only solution I found was to show the Graph after the specific tab is shown.

As you see in this jsFiddle.

var tabs = $('.tabbable').tab()  tabs.on('shown', function(e){    id = $(e.target).attr('href');            chartdiv_id = $(id).find('.chartdiv').attr('id');                            doChart(chartdiv_id, true); }); 

I guess it isn't exactly what you are looking for, but i hope it helps for the moment.



回答3:

I had the same problem, but my solution it's alternative to display:none, you can use this class in the css

.hidden {    position: absolute !important;    top: -9999px !important;    left: -9999px !important; } 

this dissapear of the screen but visible for the amchart, so the resolution of the chart never lose the size!!!!



回答4:

I completely agree with Andrzej Doyle.

Issuing handleresize on the chart when clicking on the selected div (tab) works for me on cs-cart with custom tabs (not jquery ones).

The following works while cart beeing globally defined.

    function refreshchart(){         chart.handleResize();     }; 


回答5:

I also ran into the issue and fixed it by making the initializer a function. Working fiddle.

$("#button").click(function(){     $("#chartdiv").toggle();     makeChart(); });  function makeChart() {      var chart = AmCharts.makeChart("chartdiv", {          //all the stuff      }); } 


回答6:

This Might help you to resolve issue . I have my amchart showing in different tab pan . SVG Component does not allow them to show that div due to resizing issue .

$(window).resize(function() {     setTimeout(function() {         chart.write("chartdiv1");     }, 300); }); 

resize again your window while you create your charts ..



回答7:

var chart = null; AmCharts.ready(function () {     chart = AmCharts.makeChart('chart', .....); }); $(document).ready(function(){     $("#view_chart").click(function(){         chart.validateSize();     }); });     


回答8:

Another work around would be

drawTransactionTypeChart(); setTimeout(function(){hidePieCharts();},1); 

Initially set display:inline to div which is chart container, it gets rendered .

Then set display:none using setTimeout() after 1ms.

Hope this helps...



回答9:

I have two amcharts on different tabs. A stock chart to be place on #chartdiv and a pie chart to be placed on #chartdivpie. This is how I solved my problem.

My custom css - to overwrite bootstrap -

#chartdivpie { width: 1138px; height: 500px; } .tab-content .tab-pane {    position: absolute;    top: -9999px;    left: -9999px;    display: inline; } .tab-content .tab-pane.active {     position: inherit !important; } 

JQuery call

$('#myTab a').click(function (e) {       e.preventDefault()         $(this).tab('show');         chart.invalidateSize();         chart.write('chartdiv');     }) 


回答10:

Show me charts 
some charts here


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!