Highcharts动态(重新)上浆在AngularJS标签 [英] Highcharts dynamic (re-)sizing in AngularJS tabs

查看:920
本文介绍了Highcharts动态(重新)上浆在AngularJS标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序显示HighCharts图表的各个选项卡(使用AngularJS)。需要注意的是图表上飞重新生成的每次选项卡中选择(意味着角删除或重新创建DOM树的一部分,每次)。

我的问题是,图表的大小是正确的仅在第一次的我点击一个标签。当我切换标签,所创建的图表大大超过其容器的大小。出人意料的是,图表正确的窗口大小调整大小后(即,当 chart.reflow()被调用)。

所以我尝试以下,这并没有帮助:

  $(元素).highcharts({
    图:{
      类型:'散',
      zoomType:'XY',
      事件:{
        载:函数(){
          this.reflow();
        }
      }
    },
    ...

最后,下面做工作,但它的感觉就像一个黑客攻击。

  $(元素).highcharts({
    图:{
      类型:'散',
      zoomType:'XY',
      事件:{
        载:函数(){
          VAR图=这一点;
          的setTimeout(函数(){chart.reflow();},0);
        }
      }
    },
    ...

任何想法,问题从何而来?我愿意花时间,这是pretty沮丧...

编辑:我还有一个相关的问题:默认情况下我的图表有一个给定的尺寸,但我有一个放大按钮,使他们采取充分的空间。按钮只需切换一个CSS类来做到这一点。但是,这样做确实的不可以触发resize事件,所以不会触发回流。所以,我有图表不填充它们的容器同样的问题。

下面是一个小提琴证明问题:
http://jsfiddle.net/swaek268/3/

同样,我已经找到解决问题的一种方式,但它的感觉就像一个更大的黑客攻击。

  VAR WIDTH = 0;
VAR planreflow =功能(){
  的setTimeout(函数(){
      如果(宽!== $('#集装箱')。宽度()){
          $('#集装箱')highcharts()回流()。
          的console.log('回流!)
      }
      宽度= $('#集装箱')宽()。
      planreflow();
  },10);
};
planreflow();


解决方案

我想我发现我的两个问题的解决方案:


  1. 当图完成的错误的大小装:

问题并非来自Highcharts,但是从定时创建图表时。我直接叫我的角度指令 .highcharts()链接()功能。该JS基本上看起来像这样:

  app.directive('dynamicView',函数(){
  返回{
    链接:功能(范围,元素,ATTRS){
      $(元件).highcharts({...});
    },
  };
});

由于我的元素也有一个取决于NG-如果指令的标签是否被选中与否,我想,当情况变,棱角分明的通话链接()函数确定元件的尺寸前(我猜的HTML必须是为了确定准备元件的大小)。所以我觉得这个问题是,我是叫 .highcharts()前的文件准备好了。出于某种原因,我还是不明白,元素的大小是正确的第一次NG,如果成真的话,但不正确的下一个时代。

反正溶液(仍然不是很优雅 - 但比打电话更好的回流())是延缓调用 .highcharts() 本身,以确保在创建图表时的HTML准备就绪:

 链接:功能(范围,元素,ATTRS){
  的setTimeout(函数(){
    $(元件).highcharts({...});
  },0);
}

感谢您的 @Pavel毕淑敏的有关 .highcharts()的setTimeout()的行为,您的意见

<醇开始=2>
  • 切换类时不图调整

  • 有关这个问题,我把角的事件系统的优势。

    在我的控制器控制全屏幕按钮:

      $ scope.toggleFullScreen =功能(E){
      。$ $范围广播('全屏');
    }

    此事件在层次结构,结束向上向下传递到包含图表我的指令。所有我需要做的,我创建图表时是听此事件,并引发回流()相应:

     范围。在$('全屏',函数(){
      的setTimeout(函数(){
        $(元素).highcharts()回流()。
      },0);
    });

    注意--again--的伎俩,如果我延迟与的setTimeout回流只适用()。不知道为什么。

    我希望这有助于!花了相当多的时间在这...

    My application displays HighCharts charts in various tabs (using AngularJS). Note that the charts are re-generated on the fly every time a tab is selected (Meaning that Angular "removes or recreates a portion of the DOM tree" every time).

    My problem is that the size of the chart is correct only the first time I click on a tab. When I switch tabs, the charts that are created largely exceed the size of their container. Surprisingly, the charts are correctly resized after a window resize (i.e. when chart.reflow() is called).

    So I tried the following, which did not help:

    $(element).highcharts({
        chart: {
          type: 'scatter',
          zoomType: 'xy',
          events: {
            load: function () {
              this.reflow();
            }
          }
        },
        ...
    

    Finally, the following did work, but it feels like a hack.

    $(element).highcharts({
        chart: {
          type: 'scatter',
          zoomType: 'xy',
          events: {
            load: function () {
              var chart = this;
              setTimeout(function () { chart.reflow(); }, 0);
            }
          }
        },
        ...
    

    Any idea where the problem comes from? I am spending hours on this, and this is pretty frustrating...

    EDIT: I have another related question: By default my charts have a given size, but I have an "enlarge" button to make them take the full space. The button simply toggles a CSS class to do that. However, doing this does not trigger a resize event, and so does not trigger a reflow. So I have the same problem of charts not filling their container.

    Here is a fiddle to demonstrate the issue: http://jsfiddle.net/swaek268/3/

    Again, I have found a way around the problem, but it feels like an even bigger hack.

    var width = 0;
    var planreflow = function(){
      setTimeout(function(){
          if(width!==$('#container').width()){
              $('#container').highcharts().reflow(); 
              console.log('reflow!')
          }
          width = $('#container').width();
          planreflow();
      }, 10);
    };
    planreflow();
    

    解决方案

    I think I found solutions to both of my problems:

    1. Wrong size when chart finishes loading:

    The problem does not come from Highcharts, but from the timing when the chart is created. I directly called .highcharts() from the link() function of my Angular directive. The JS looking essentially like this:

    app.directive('dynamicView', function() {
      return {
        link: function(scope, element, attrs){
          $(element).highcharts({...});
        },    
      };
    });
    

    As my element also has a ng-if directive depending on whether the tab is selected or not, I imagine that when that condition turns true, angular calls the link() function before the dimension of the element is determined (I guess the HTML has to be ready in order to determine the size of the elements). So I think the problem was that I was calling .highcharts() before the document was ready. For some reason that I still don't understand, the size of the element is correct the first time ng-if turns true, but incorrect the next times.

    Anyway, a solution (still not very elegant - but better than calling reflow()) is to delay the call to .highcharts() itself, to make sure that the HTML is ready when creating the charts:

    link: function(scope, element, attrs){
      setTimeout(function () {
        $(element).highcharts({...});
      }, 0);
    }
    

    Thank you @Pavel Fus for your comments on the behaviour of .highcharts() and setTimeout().

    1. Chart not resizing when toggling a class

    For this problem I took advantage of Angular's eventing system.

    In my controller controlling the full-screen button:

    $scope.toggleFullScreen = function(e){
      $scope.$broadcast('fullscreen');
    }
    

    This event is passed down the hierarchy, ending-up to my directives containing the charts. All I have to do, when creating my charts is to listen to this event, and trigger a reflow() accordingly:

    scope.$on('fullscreen', function(){
      setTimeout(function () { 
        $(element).highcharts().reflow(); 
      }, 0);
    });
    

    Note that --again-- the trick only works if I delay the reflow with setTimeout(). Not sure why.

    I hope this helps! Spent quite a bit of time on this...

    这篇关于Highcharts动态(重新)上浆在AngularJS标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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