amCharts 不显示最初隐藏的 div 的图表 [英] amCharts doesn't display chart for initially-hidden divs

查看:34
本文介绍了amCharts 不显示最初隐藏的 div 的图表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 amCharts(使用 Raphaël 在幕后)将一些图表渲染为 SVG;并且已经注意到,如果 SVG 在最初不可见的 div 中呈现,当 div 变得可见时,浏览器不会立即呈现图像.但是,如果我修改显示,例如通过调整浏览器大小或 Ctrl-鼠标滚轮缩放,SVG 图像会在页面重绘时按预期呈现.

I am using amCharts (which uses Raphaël 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.

div 可见性切换的确切方法是通过 Bootstrap 的标签式导航栏.

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

我承认我对 SVG 的经验不是很丰富——这是浏览器渲染的问题,还是 amCharts 的 SVG 标记问题,还是当我知道 SVG 的可见性时我需要明确调用某种重绘方法变了吗?

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?

这是一个 jsFiddle 说明了问题;如果您切换到第 2 部分(在 Chrome、Firefox 中),图表最初是不可见的.调整显示大小使其出现.

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.

推荐答案

我已经找到了初始行为和解决方法的原因 - 这都是 amCharts 特定的(与 SVG 本身无关)所以我相应地改写标题.

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.

发生的情况是,当 amCharts 创建 SVG 时,它需要(或至少决定)以绝对值定义宽度和高度.这些基于目标 div 的大小,通过 offsetWidthoffsetHeight 属性获得.

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.

非活动选项卡设置了 display: none 属性,因此这部分 DOM 甚至没有呈现,因此对于两个 size 属性都返回零.这最终导致 amCharts 在为隐藏的 div 调用 chart.write 时创建一个 0x0 SVG 图表.

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.

调整大小可以解决问题,因为每个图表都会向 onresize 窗口事件注册一个侦听器,该事件调用图表的 handleResize 方法.这会强制根据 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:

  • 当且仅当其选项卡可见时,为图表调用 chart.write.
  • 当标签更改时调用每个图表的 handleResize 方法.

(第一个选项避免了渲染不可见图表的初始命中,但每次更改选项卡时都会进行完整的重绘.后者需要预先命中,但此后可能会更快.对于奖励分数,最好的解决方案是在每次调整大小之间只渲染每个图表一次,第一次变得可见,但这要复杂得多,因为它涉及干扰默认事件侦听器等.)

(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.)

更新:渲染不可见图表还有更多复杂性;特别是,我发现高度计算存在问题,没有考虑域轴所需的空间,因此将图表从其 div 中拉伸出来.这不是通过调用 handleResize 来解决的 - 预先调用 measureMargins 看起来应该可以工作但没有.(可能还有另一种方法可以在此之后调用以使其工作,例如 resetMargins 但此时它开始感觉非常不稳定......)

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...)

因此,我认为第一次在不可见的 div 上渲染图表是不切实际的,所以我使用了上面的一些项目符号组合.我倾听第一次可见图表的选项卡,然后调用 chart.write 获取相应的图表对象 - 并且只要制表符更改,所有以前渲染的图表被告知处理调整大小.

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.

这篇关于amCharts 不显示最初隐藏的 div 的图表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆