我正在使用amCharts(在幕后使用Raphaël)将一些图表渲染为SVG;并且注意到如果SVG在最初不可见的div中渲染,则当div变为可见时,浏览器不会立即渲染图像。但是,如果我修改显示,例如通过调整浏览器大小或按Ctrl-鼠标滚轮缩放,SVG图像将在重绘页面时按预期呈现。
div可见性切换的确切方法是通过Bootstrap's tabbed navbar。
我承认对SVG不是很有经验 - 这是浏览器渲染或amCharts的SVG标记的问题,或者当我能告诉SVG的可见性时,我需要显式调用某种重绘方法已经改变了?
这是一个jsFiddle which illustrates the problem;如果您切换到第2部分(在Chrome,Firefox中),则图表最初不可见。调整显示大小会使其显示。
答案 0 :(得分:24)
我找到了初始行为和解决方法的原因 - 并且它都是特定的amCharts(与SVG本身无关)所以我相应地重新标记了这个标题。
当amCharts创建SVG时,它需要(或至少决定)以绝对值定义宽度和高度。这些是基于目标div的大小,通过offsetWidth
和offsetHeight
属性获得。
非活动选项卡设置了display: none
属性,因此DOM的这部分甚至不会被渲染,因此两个大小属性都返回零。这最终会导致amCharts在为隐藏div调用chart.write
时创建一个0x0 SVG图表。
调整大小修复因为每个图表都会向onresize
窗口事件注册一个监听器,该事件调用图表的handleResize
方法。这会强制根据div的新(当前)尺寸重新计算宽度和高度。
总而言之,我认为有两种方法可以解决这个问题:
chart.write
以获取图表。handleResize
方法。(第一个选项避免了渲染不可见图表的初始命中,但每次更改标签时都会进行完全重绘。后者需要预先点击,但此后可能更快。对于奖励分数,最好解决方案是在每次调整大小之间呈现每个图表一次,第一次变为可见,但这会更复杂,因为它会涉及干扰默认事件监听器等等。)
更新:呈现不可见的图表会更加复杂化;特别是,我发现高度计算的问题没有考虑域轴所需的空间,因此将图表拉出其div。调用handleResize
并未解决此问题 - 事先调用measureMargins
看起来应该可以正常工作但却没有。 (可能有一种方法可以在此之后调用它以使其工作,例如resetMargins
,但此时它开始感觉非常不稳定...)
因此我认为在不可见的div上首次渲染图表是不切实际的,所以我选择了上面的子弹组合。我在第一次看到图表的标签时会听到,然后为相应的图表对象调用chart.write
- 每当标签发生变化时,所有之前呈现的图表都被告知要处理调整大小。
答案 1 :(得分:4)
*已编辑*
这是更新的fiddle。只有在显示选项卡后才会呈现画布。 我将chartdiv id存储在一个数组中,并检查其中是否存在。
*已编辑*
我找到的唯一解决方案是在显示特定标签后显示图表。
正如您在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);
});
我想这并不是你想要的,但我希望它暂时有用。
答案 2 :(得分:3)
我遇到了同样的问题,但是我的解决方案是display的替代方法:none,你可以在css中使用这个类
.hidden {
position: absolute !important;
top: -9999px !important;
left: -9999px !important;
}
这个屏幕的消失但是对于amchart是可见的,所以图表的分辨率永远不会丢失!!!!
答案 3 :(得分:1)
我完全赞同Andrzej Doyle。
单击选定的div(选项卡)时,在图表上发出handleresize对我来说适用于带有自定义选项卡(而不是jquery)的cs-cart。
以下内容适用于全球定义的购物车。
function refreshchart(){
chart.handleResize();
};
答案 4 :(得分:1)
这可能会帮助您解决问题。我在不同的标签盘中显示我的amchart。由于调整大小问题,SVG组件不允许它们显示该div。
$(window).resize(function() {
setTimeout(function() {
chart.write("chartdiv1");
}, 300);
});
在创建图表时再次调整窗口大小..
答案 5 :(得分:1)
我也遇到了问题并通过使初始化程序成为函数来修复它。 Working fiddle
$("#button").click(function(){
$("#chartdiv").toggle();
makeChart();
});
function makeChart() {
var chart = AmCharts.makeChart("chartdiv", {
//all the stuff
});
}
答案 6 :(得分:1)
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>
答案 7 :(得分:1)
<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>
答案 8 :(得分:0)
另一种解决方法是
drawTransactionTypeChart();
setTimeout(function(){hidePieCharts();},1);
最初将display:inline
设置为div作为图表容器,它将被渲染。
然后在1ms后使用display:none
设置setTimeout()
。
希望这会有所帮助......
答案 9 :(得分:0)
我在不同的标签上有两个amcharts 。 要放在#chartdiv上的股票图表和要放在#chartdivpie上的饼图。 这就是我解决问题的方法。
我的自定义css - 覆盖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调用
$('#myTab a').click(function (e) {
e.preventDefault()
$(this).tab('show');
chart.invalidateSize();
chart.write('chartdiv');
})