首页 文章

AngularJS选项卡中的Highcharts动态(重新)大小调整

提问于
浏览
9

我的应用程序在各种选项卡中显示HighCharts图表(使用AngularJS) . 请注意,图表是在动态重新生成的 every time a tab is selected (意思是每次都是Angular "removes or recreates a portion of the DOM tree") .

我的问题是,只有在我第一次点击选项卡时,图表的大小才是正确的 . 切换选项卡时,创建的图表大大超过了容器的大小 . 令人惊讶的是,在调整窗口大小(即调用 chart.reflow() )后,图表会正确调整大小 .

所以我尝试了以下,但没有帮助:

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

最后,以下确实有效,但感觉就像是黑客 .

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

知道问题的来源吗?我花了好几个小时,这非常令人沮丧......

编辑:我有另一个相关的问题:默认情况下,我的图表有一个给定的大小,但我有一个"enlarge"按钮,使他们占用整个空间 . 该按钮只是切换一个CSS类来做到这一点 . 但是,执行此操作会触发调整大小事件,因此不会触发重排 . 所以我有同样的问题,图表没有填充他们的容器 .

这是一个演示该问题的小提琴:http://jsfiddle.net/swaek268/3/

我再次找到解决问题的方法,但感觉就像是一个更大的黑客 .

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

2 回答

  • 1

    我想我找到了解决我的两个问题的方法:

    • Wrong size when chart finishes loading:

    问题不是来自Highcharts,而是来自创建图表的时间 . 我直接从我的Angular指令的 link() 函数中调用 .highcharts() . JS看起来基本上是这样的:

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

    由于我的元素也有一个 ng-if 指令取决于是否选中了标签,我想当该条件变为 true 时,angular会在确定元素的维度之前调用 link() 函数(我想HTML必须准备就绪)以确定元素的大小) . 所以我认为问题是我在文档准备好之前调用了 .highcharts() . 由于某种原因,我仍然不明白,第一次ng-if变为true时元素的大小是正确的,但下次不正确 .

    无论如何,一个解决方案(仍然不是很优雅 - 但比调用 reflow() 更好)是延迟调用 .highcharts() 本身,以确保在创建图表时HTML已准备好:

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

    感谢@Pavel Fus对 .highcharts()setTimeout() 行为的评论 .

    • Chart not resizing when toggling a class

    对于这个问题,我利用了Angular的事件系统 .

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

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

    此事件在层次结构中传递,最终到我的包含图表的指令 . 在创建图表时,我只需要听取此事件,并相应地触发 reflow()

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

    注意--again--这个技巧只有在我用 setTimeout() 延迟回流时才有效 . 不知道为什么 .

    我希望这有帮助!在这上花了不少时间......

  • 7

    所以,实际上你有两个问题:

    1)第二次点击时尺寸不正确 . 这很可能是由于隐藏( display: none )容器的宽度和高度错误造成的 . 在这种情况下,浏览器报告的宽度/高度不正确(如 0px ) . 同样的问题herehere .

    2)为容器设置类不会触发图表的 resize (或更确切地说是 reflow )事件 . 这意味着您需要自己调用 chart.reflow() . 我建议你在改变 class 时在同一个地方做这件事 .

相关问题