AngularJS-绑定到指令调整大小

AngularJS-绑定到指令调整大小,angularjs,angularjs-directive,Angularjs,Angularjs Directive,调整指令大小时如何通知我? 我试过了 element[0].onresize = function() { console.log(element[0].offsetWidth + " " + element[0].offsetHeight); } 但它并没有调用函数 (function() { 'use strict'; // Define the directive on the module. // Inject the dependencies

调整指令大小时如何通知我? 我试过了

element[0].onresize = function() {
            console.log(element[0].offsetWidth + " " + element[0].offsetHeight);
        }
但它并没有调用函数

(function() {
'use strict';

// Define the directive on the module.
// Inject the dependencies. 
// Point to the directive definition function.
angular.module('app').directive('nvLayout', ['$window', '$compile', layoutDirective]);

function layoutDirective($window, $compile) {
    // Usage:
    // 
    // Creates:
    // 
    var directive = {
        link: link,
        restrict: 'EA',
        scope: {
            layoutEntries: "=",
            selected: "&onSelected"
        },
        template: "<div></div>",
        controller: controller
    };
    return directive;

    function link(scope, element, attrs) {
        var elementCol = [];

        var onSelectedHandler = scope.selected();

        element.on("resize", function () {
            console.log("resized.");
        });

        $(window).on("resize",scope.sizeNotifier);

        scope.$on("$destroy", function () {
            $(window).off("resize", $scope.sizeNotifier);
        });

        scope.sizeNotifier = function() {
            alert("windows is being resized...");
        };

        scope.onselected = function(id) {
            onSelectedHandler(id);
        };



        scope.$watch(function () {
            return scope.layoutEntries.length;
        },
        function (value) {
            //layout was changed
            activateLayout(scope.layoutEntries);
        });

        function activateLayout(layoutEntries) {


            for (var i = 0; i < layoutEntries.length; i++) {

                if (elementCol[layoutEntries[i].id]) {
                    continue;
                }
                var div = "<nv-single-layout-entry id=slot" + layoutEntries[i].id + " on-selected='onselected' style=\"position:absolute;";
                div = div + "top:" + layoutEntries[i].position.top + "%;";
                div = div + "left:" + layoutEntries[i].position.left + "%;";
                div = div + "height:" + layoutEntries[i].size.height + "%;";
                div = div + "width:" + layoutEntries[i].size.width + "%;";
                div = div + "\"></nv-single-layout-entry>";

                var el = $compile(div)(scope);
                element.append(el);
                elementCol[layoutEntries[i].id] = 1;
            }


        };
    }

    function controller($scope, $element) {

    }
}

      })();
(函数(){
"严格使用",;
//在模块上定义指令。
//注入依赖项。
//指向指令定义函数。
angular.module('app').directive('nvLayout',['$window','$compile','layoutDirective]);
函数layoutDirective($window,$compile){
//用法:
// 
//创建:
// 
var指令={
链接:链接,
限制:“EA”,
范围:{
布局:“=”,
已选择:“&onSelected”
},
模板:“”,
控制器:控制器
};
返回指令;
功能链接(范围、元素、属性){
var elementCol=[];
var onSelectedHandler=scope.selected();
元素上(“调整大小”,函数(){
log(“调整大小”);
});
$(窗口).on(“调整大小”,scope.sizeNotifier);
作用域:“$destroy”,函数(){
$(window).off(“resize”、$scope.sizeNotifier);
});
scope.sizeNotifier=函数(){
警报(“正在调整窗口大小…”);
};
scope.onselected=函数(id){
onSelectedHandler(id);
};
范围:$watch(函数(){
返回scope.layounterties.length;
},
函数(值){
//布局已更改
activateLayout(范围、布局);
});
函数activateLayout(layoutEntries){
for(var i=0;i
以下是您需要执行的操作的示例代码:

APP.directive('nvLayout', function ($window) {
  return {
    template: "<div></div>",
    restrict: 'EA',
    link: function postLink(scope, element, attrs) {

      scope.onResizeFunction = function() {
        scope.windowHeight = $window.innerHeight;
        scope.windowWidth = $window.innerWidth;

        console.log(scope.windowHeight+"-"+scope.windowWidth)
      };

      // Call to the function when the page is first loaded
      scope.onResizeFunction();

      angular.element($window).bind('resize', function() {
        scope.onResizeFunction();
        scope.$apply();
      });
    }
  };
});
APP.directive('nvLayout',函数($window){
返回{
模板:“”,
限制:“EA”,
链接:函数postLink(范围、元素、属性){
scope.onResizeFunction=函数(){
scope.windowHeight=$window.innerHeight;
scope.windowWidth=$window.innerWidth;
console.log(scope.windowHeight+“-”+scope.windowWidth)
};
//首次加载页面时调用函数
scope.onResizeFunction();
angular.element($window.bind('resize',function()){
scope.onResizeFunction();
作用域:$apply();
});
}
};
});
与自定义手表功能一起使用:

scope.$watch(
  function () {
    return [element[0].offsetWidth, element[0].offsetHeight].join('x');
  },
  function (value) {
    console.log('directive got resized:', value.split('x'));
  }
)
app.directive('myDirective', [function() {

    function link($scope, element) {
        var container = element[0];

        $scope.$watchGroup([
            function() { return container.offsetWidth; },
            function() { return container.offsetHeight; }
        ],  function(values) {
              // Handle resize event ...
        });
    }

    // Return directive definition ...

}]);

使用$watch检测元素大小/位置变化的唯一方法是使用$interval或$timeout之类的东西不断更新范围。虽然有可能,但它可能会成为一项昂贵的操作,并真正降低应用程序的速度

检测元素更改的一种方法是调用
requestAnimationFrame

var previousPosition = element[0].getBoundingClientRect();

onFrame();

function onFrame() {
  var currentPosition = element[0].getBoundingClientRect();

  if (!angular.equals(previousPosition, currentPosition)) {
    resiszeNotifier();
  }

  previousPosition = currentPosition;
  requestAnimationFrame(onFrame);
}

function resiszeNotifier() {
  // Notify...
}
这是一个演示这一点的砰砰声。只要你移动盒子,它就会保持红色


您通常希望查看元素的
偏移网络宽度
偏移网络宽度
属性。对于AngularJS的最新版本,您可以在链接函数中使用
$scope.$watchGroup

scope.$watch(
  function () {
    return [element[0].offsetWidth, element[0].offsetHeight].join('x');
  },
  function (value) {
    console.log('directive got resized:', value.split('x'));
  }
)
app.directive('myDirective', [function() {

    function link($scope, element) {
        var container = element[0];

        $scope.$watchGroup([
            function() { return container.offsetWidth; },
            function() { return container.offsetHeight; }
        ],  function(values) {
              // Handle resize event ...
        });
    }

    // Return directive definition ...

}]);
但是,在以这种方式直接查看元素属性时,您可能会发现更新非常慢

为了使指令更具响应性,可以使用
$interval
调节刷新率。下面是一个可重用服务的示例,用于以可配置的毫秒速率查看元素大小:

app.factory('sizeWatcher', ['$interval', function($interval) {
    return function (element, rate) {
        var self = this;
        (self.update = function() { self.dimensions = [element.offsetWidth, element.offsetHeight]; })();
        self.monitor = $interval(self.update, rate);
        self.group = [function() { return self.dimensions[0]; }, function() { return self.dimensions[1]; }];
        self.cancel = function() { $interval.cancel(self.monitor); };
    };
}]);
使用此类服务的指令如下所示:

app.directive('myDirective', ['sizeWatcher', function(sizeWatcher) {

    function link($scope, element) {
        var container = element[0],
            watcher = new sizeWatcher(container, 200);

        $scope.$watchGroup(watcher.group, function(values) {
            // Handle resize event ...
        });

        $scope.$on('$destroy', watcher.cancel);
    }

    // Return directive definition ...

}]);
注意在
$scope.$destroy
事件处理程序中调用
watcher.cancel()
;这确保不再需要时销毁
$interval
实例


可以找到一个JSFIDLE示例。

Eliel的答案有一点变化,这对我很有用。在directive.js中:

      $scope.onResizeFunction = function() {
      };

      // Call to the function when the page is first loaded
      $scope.onResizeFunction();

      angular.element($(window)).bind('resize', function() {
        $scope.onResizeFunction();
        $scope.$apply();
      });
我打电话

    $(window).resize();

从我的app.js中。该指令的d3图表现在可以调整大小以填充容器。

以下是我对该指令的看法(使用
Webpack
作为捆绑包):


我试着理解代码的目的,但这对我来说很难。我已经消除了代码对JQuery的依赖,您可以在这里检查:我只是想在调整指令元素的大小时得到通知。我可以听整个页面,但我想知道elemnt何时导致指令move@li-raz:完全实现:-)如果只调整指令get的大小,而不调整窗口本身,这将不起作用。。。虽然我不认为你需要调用Apply,但我已经尝试过了,但它通常会向我显示旧的值。我有一个边栏,可以使用按钮隐藏或显示,当我单击时,摘要循环发生,watch函数告诉我元素的大小没有改变,然后元素被调整大小,这会在下一个循环中出现,从而导致故障。有什么想法吗?@HernanRajchert(以及任何其他未来的读者),这是因为可以计算为CSS高度+CSS填充-水平滚动条的高度(如果存在)。你想要的是。观看
元素[0]。远视(和宽度)应该可以。@JordanCarroll对我来说,使用远视而不是clientHeight并没有解决问题。你说得对,我相应地调整了答案。感谢您指出这一点。我对digest cycle也有同样的问题,resize事件只在下一次调用时触发。我的问题在这里。不幸的是,看着OutthItHeal/Stand似乎没有解决这个问题。任何想使用这个方法的人都应该考虑替换<代码> $间隔(Self.Up更新,Read);<代码>具有
$interval(self.update,rate,0,false),它明确表示最后不要调用$apply。否则,范围的摘要将为ca