Javascript amCharts 不显示最初隐藏的 div 的图表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10013408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
amCharts doesn't display chart for initially-hidden divs
提问by Andrzej Doyle
I am using amCharts(which uses Rapha?lbehind 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.
我正在使用amCharts(在幕后使用Rapha?l)将一些图表渲染为 SVG;并且已经注意到,如果 SVG 在最初不可见的 div 中呈现,当 div 变得可见时,浏览器不会立即呈现图像。但是,如果我修改显示,例如通过调整浏览器的大小或 Ctrl-鼠标滚轮缩放,则在重新绘制页面时会按预期呈现 SVG 图像。
The exact method of div visibility switching is via Bootstrap's tabbed navbar.
div 可见性切换的确切方法是通过Bootstrap 的选项卡式导航栏。
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?
我承认我对 SVG 不是很熟悉——这是浏览器渲染的问题,还是 amCharts 的 SVG 标记问题,还是当我知道 SVG 的可见性发生了变化时,我是否需要明确调用某种重绘方法?
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.
这是一个jsFiddle,它说明了这个问题;如果您切换到第 2 部分(在 Chrome、Firefox 中),图表最初是不可见的。调整显示大小使其出现。
回答by Andrzej Doyle
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 本身无关),所以我相应地重新表述了标题。
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.
发生的情况是,当 amCharts 创建 SVG 时,它需要(或至少决定)以绝对形式定义宽度和高度。这些基于目标 div 的大小,通过offsetWidth
和offsetHeight
属性获得。
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.
非活动选项卡display: none
设置了属性,因此这部分 DOM 甚至没有呈现,因此两个 size 属性都返回零。这最终导致 amCharts 在chart.write
调用隐藏 div时创建一个 0x0 SVG 图表。
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.
调整大小可以解决问题,因为每个图表都会向onresize
window 事件注册一个侦听器,该事件调用图表的handleResize
方法。这会强制根据 div 的新(当前)尺寸重新计算宽度和高度。
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.
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.)
(第一个选项避免了渲染不可见图表的初始命中,但每次更改选项卡时都会进行完全重绘。后者需要预先命中,但此后可能会更快。对于奖励分数,最佳解决方案是在每次调整大小之间只渲染每个图表一次,它第一次变得可见,但这要复杂得多,因为它会涉及干扰默认事件侦听器等。)
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 中拉伸出来。这不是通过调用来解决的handleResize
-measureMargins
预先调用看起来应该可以工作但没有。(可能还有另一种方法可以在此之后调用以使其工作,例如resetMargins
但此时它开始感觉非常不稳定......)
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, allpreviously-rendered charts are told to handle the resize.
因此,我认为第一次在不可见的 div 上渲染图表是不切实际的,所以我使用了上面的一些项目符号组合。我倾听第一次可见图表的选项卡,然后调用chart.write
适当的图表对象 - 并且只要制表符更改,都会告诉所有以前呈现的图表以处理调整大小。
回答by Robert Merten
* 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.
这是一个更新的小提琴。只有在显示选项卡后才会呈现画布。我将 chartdiv id 存储在一个数组中并检查其中是否存在。
* Edited *
* 编辑 *
The only solution I found was to show the Graph after the specific tab is shown.
我找到的唯一解决方案是在显示特定选项卡后显示图表。
As you see in this jsFiddle.
正如你在这个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.
我想这不完全是你要找的东西,但我希望它暂时有所帮助。
回答by DonVidela
I had the same problem, but my solution it's alternative to display:none, you can use this class in the css
我遇到了同样的问题,但我的解决方案是 display:none 的替代方案,您可以在 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!!!!
屏幕消失但对 amchart 可见,因此图表的分辨率永远不会丢失大小!!!!
回答by chetnashahu
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 .
这可能会帮助您解决问题。我的 amchart 显示在不同的 tab pan 中。由于调整大小问题,SVG 组件不允许他们显示该 div。
$(window).resize(function() {
setTimeout(function() {
chart.write("chartdiv1");
}, 300);
});
resize again your window while you create your charts ..
创建图表时再次调整窗口大小..
回答by Perry
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
});
}
回答by yassine
var chart = null;
AmCharts.ready(function () {
chart = AmCharts.makeChart('chart', .....);
});
$(document).ready(function(){
$("#view_chart").click(function(){
chart.validateSize();
});
});
<button type="button" id="view_chart">View Chart</button>
<div style="display:none;" id="chart"></div>
回答by RSV_70
<a href="#" class="show_charts">Show me charts</a>
<div class="charts_div" style="display:hidden;">
some charts here
</div>
<script>
$(document).on('click', '.show_charts', function(){
$('.charts_div').toggle();
//just redraw all charts available on the page
for(var i = 0; i < AmCharts.charts.length; i++) {
AmCharts.charts[i].validateData();
}
});
</script>
回答by 426 - Your digital upgrade
I completely agree with Andrzej Doyle.
我完全同意 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).
在带有自定义选项卡(不是 jquery 选项卡)的 cs-cart 上单击选定的 div(选项卡)时,在图表上发出 handleresize 对我有用。
The following works while cart beeing globally defined.
当购物车被全局定义时,以下工作。
function refreshchart(){
chart.handleResize();
};
回答by PJunior
I have two amchartson 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.
我在不同的选项卡上有两个 amcharts。一个股票图表放在#chartdiv 上,一个饼图放在#chartdivpie 上。这就是我解决我的问题的方法。
My custom css - to overwrite bootstrap -
我的自定义 css - 覆盖引导程序 -
#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
JQuery 调用
$('#myTab a').click(function (e) {
e.preventDefault()
$(this).tab('show');
chart.invalidateSize();
chart.write('chartdiv');
})
回答by Chakradhar Vyza
Another work around would be
另一种解决方法是
drawTransactionTypeChart();
setTimeout(function(){hidePieCharts();},1);
Initially set display:inline
to div which is chart container, it gets rendered .
最初设置display:inline
为图表容器 div ,它被渲染。
Then set display:none
using setTimeout()
after 1ms.
然后在1ms后设置display:none
使用setTimeout()
。
Hope this helps...
希望这可以帮助...