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

Highcharts dynamic (re-)sizing in AngularJS tabs

本文关键字:重新 调整 动态 AngularJS 选项      更新时间:2023-09-26

我的应用程序在不同的选项卡中显示HighCharts图表(使用AngularJS)。请注意,每次选择选项卡时,图表都会在动态中重新生成(这意味着Angular每次都会"删除或重新创建DOM树的一部分")。

我的问题是,图表的大小是正确的只有第一次我点击一个标签。当我切换选项卡时,创建的图表很大程度上超过了其容器的大小。令人惊讶的是,图表在窗口大小调整后正确地调整了大小(即当chart.reflow()被调用时)。

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

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

最后,下面的代码可以工作了,但是感觉像是一个hack。

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

你知道问题出在哪里吗?我花了几个小时在这上面,这真是令人沮丧……

编辑:我有另一个相关的问题:默认情况下,我的图表有一个给定的大小,但我有一个"放大"按钮,使他们占据整个空间。按钮只是切换一个CSS类来实现这一点。然而,这样做不会触发调整大小事件,因此不会触发流。所以我也有同样的问题,图表没有填满它们的容器。

下面是一个小提琴来演示这个问题:http://jsfiddle.net/swaek268/3/

我又找到了一个解决问题的方法,但感觉像是一个更大的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();

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

  1. 图表加载完成时尺寸错误:

问题不是来自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时是正确的,但在下一次变为true时就不正确了。

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

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

谢谢你@Pavel Fus.highcharts()setTimeout()行为的评论。

  • 切换类时图表不调整大小
  • 对于这个问题,我利用了Angular的事件处理系统。

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

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

    该事件向下传递到包含图表的指令。在创建图表时,我所要做的就是听这个事件,并相应地触发reflow():

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

    注意——再次——这个技巧只有在我用setTimeout()延迟回流时才有效。不知道为什么。

    我希望这对你有帮助!

    实际上你有两个问题:

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

    2)为容器设置类不会为图表触发resize(或者更确切地说是reflow)事件。这意味着您需要自己调用chart.reflow()