【问题标题】:amCharts doesn't display chart for initially-hidden divsamCharts 不显示最初隐藏的 div 的图表
【发布时间】:2012-04-18 07:06:29
【问题描述】:

我正在使用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 中),图表最初是不可见的。调整显示大小会使其出现。

【问题讨论】:

标签: javascript svg rendering


【解决方案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>

【讨论】:

    【解决方案2】:
    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>
    

    【讨论】:

      【解决方案3】:

      这可能会帮助您解决问题。我的 amchart 显示在不同的选项卡 pan 中。由于调整大小问题,SVG 组件不允许他们显示该 div。

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

      在创建图表时再次调整窗口大小 ..

      【讨论】:

        【解决方案4】:

        我也遇到了这个问题,并通过使初始化程序成为一个函数来解决它。 Working fiddle.

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

        【讨论】:

          【解决方案5】:

          我有同样的问题,但我的解决方案是 display:none,你可以在 css 中使用这个类

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

          屏幕消失,但对 amchart 可见,因此图表的分辨率永远不会丢失大小!!!!

          【讨论】:

            【解决方案6】:

            我在不同的标签上有两个 amcharts。 将放置在#chartdiv 上的股票图表和将放置在#chartdivpie 上的饼图。 这就是我解决问题的方法。

            我的自定义 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 调用

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

            【讨论】:

              【解决方案7】:

              我完全同意 Andrzej Doyle。

              单击选定的 div(选项卡)时在图表上发出 handleresize 对我来说适用于带有自定义选项卡(不是 jquery 选项卡)的 cs-cart。

              在全局定义购物车时以下工作。

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

              【讨论】:

                【解决方案8】:

                另一种解决方法是

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

                最初将display:inline设置为图表容器的div,它会被渲染。

                然后在 1ms 后使用setTimeout() 设置display:none。

                希望对你有帮助……

                【讨论】:

                  【解决方案9】:

                  我已经找到了初始行为和解决方法的原因 - 这都是 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 上渲染图表是不切实际的,所以我结合了上面的项目符号。 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.

                  【讨论】:

                    【解决方案10】:

                    * 已编辑 *

                    这是更新后的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);
                    });
                    

                    我想这不是您正在寻找的东西,但我希望它暂时对您有所帮助。

                    【讨论】:

                    • 感谢您的工作和更新。目前,您的最新版本中仍有一个错误(尽管是一个小错误) - 如果您在选项卡之间切换,然后调整浏览器大小,两个图表都会触发重绘,我们又回到了原点一。这就是为什么我提出的第一个解决方案包括每次标签变为活动状态时编写图表(例如forked fiddle),它克服了任何中间调整大小的影响。
                    • 没问题。我错过了。我相信每次重绘图表可能是最好的解决方案。感谢您的支持!一直在这里寻找解决我问题的方法,但从未参与过,我想我会尝试帮助其他人解决问题以做出改变。
                    • 我接受了我自己的回答,因为它解释了我实际使用的内容,但再次感谢您的帮助。特别是,您确定激活的特定选项卡的想法对于防止绘图区域边距被拉伸非常重要。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-07-20
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多