javascript - 加载内部指令后访问子元素图像

标签 javascript angularjs angularjs-directive

我正在尝试创建一个指令来对子图像执行缩放。使用 ng-repeat 嵌入图像,URL 来自父 Controller 中的 REST API 调用。这是指令的嵌入:

这是该指令的模板:

<div>
    <img image-directive-item ng-src="{{image.url}}" ng-style="{'width': {{image.width}}, 'height': {{image.height}}}" ng-if="image.done" />
</div>

要缩放每个图像,我需要有关其周围其他图像的宽度/高度的信息。目前,我正在尝试在绑定(bind)到图像的子指令中加载时将此信息传递给父级。这是我正在测试的代码:

angular.module("myApp")
.directive("imageDirective", function() {
    return {
        scope: { images: '=images'},
        link: function(scope){

            for(var i = 0; i < scope.images.length; i++) {
                console.log(scope.images[i].width, scope.images[i].height);
            }

        },
        templateUrl: _contextPath + 'static/html/imageDirective.html'
    };
})
.directive("imageDirectiveItem", function() {
    return {
        link: function(scope, element) {
            element.bind("load", function(e) {
                scope.image.width = this.naturalWidth;
                scope.image.height = this.naturalHeight;
            });
        }
    };
});

图像正在页面上加载,并且加载回调可以读取尺寸,但是控制台中的输出(来自父指令)对于所有图像都是“未定义未定义”,并且出现有关无法设置尺寸的错误宽度/高度为空值。

我想以这种格式执行此操作,因为我需要按照图像在 DOM 中出现的顺序处理图像。然而,我正在努力让两者联系起来,而不需要诉诸黑客的手段。有什么想法吗?


下面由 New Dev 提供的解决方案对我有用。修改了元素传递给父指令的方式,以便它从加载回调传递对象,其中包含我需要的信息。今天学到了一些关于 Angular 的新知识!

angular.module("myApp")
.directive("imageDirective", function() {
    return {
        scope: { images: '=images'},
        controller: function($scope){

            var toBeLoaded = $scope.images.length;

            this.childLoaded = function(childElement) {
                console.log(childElement.naturalWidth, childElement.naturalHeight);

                if(--toBeLoaded == 0) {
                    allChildrenLoaded();
                }
            };

            function allChildrenLoaded() {
                console.log("All children loaded.");
            }

        },
        templateUrl: _contextPath + 'static/html/imageGrid.html'
    };
})
.directive("imageDirectiveItem", function() {
    return {
        require: "^imageDirective",
        link: function(scope, element, attrs, imageDirectiveCtrl) {
            element.bind("load", function() {
                var e = this;
                scope.$apply(function() {
                    imageDirectiveCtrl.childLoaded(e);
                });
            });
        }
    };
});

控制台输出:

414 415
507 338
366 468
432 395
500 354
507 338
414 414
478 358
507 338
All children loaded.

最佳答案

您打印 undefined undefined 的原因是因为您在执行 for 循环时尚未加载任何图像。

如果您需要在父级中“处理”(如您所说)结果,那么在范围公开的对象上设置值可能不是最好的方法。例如,您如何知道它已完成加载?如果没有昂贵的深度$watch,你怎么知道某些事情已经发生了变化?

我认为更好的方法是公开子指令可以调用的 API。这是通过在父 Controller 上公开一个函数并在子 Controller 上使用 require: "^imageDirective" 来完成的。

.directive("imageDirective", function(){
  return {
    // .. whatever you currently have
    controller: function($scope){
      var toBeLoaded = 0;
      this.registerChild = function(childElem){
         toBeLoaded++;
      };

      this.childLoaded = function(childElem){
         toBeLoaded--;
         // do whatever processing you need
      };
    }
  }
})
.directive("imageDirectiveItem", function(){
  return {
    require: "^imageDirective",
    link: function(scope, element, attrs, imageDirectiveCtrl){
       imageDirectiveCtrl.registerChild(element);

       element.bind("load", function(){
          scope.$apply(function(){
             imageDirectiveCtrl.childLoaded(element);
          })
       })
    }
  }
}

关于javascript - 加载内部指令后访问子元素图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29033286/

相关文章:

javascript - 当必填字段未填写时,不会调用 Angular 提交

javascript - 低延迟 websocket html 5 游戏的数据包大小

javascript - ng-bind-html html 与 css 不起作用

javascript - AngularJS - 处理现有 DOM 元素上的点击事件

javascript - Angular 指令 - 函数执行的正确顺序

javascript - 正则表达式不仅可以匹配两个特定符号之间的字符,还可以匹配单个符号之后的字符

javascript - 删除特定的事件处理程序

javascript - 将模型属性方法发送到客户端 Sails Angular

javascript - AngularJS 递归模板渲染

javascript - AngularJS : Scope is not shared between nested transcluded directives