Événement chargé d'image dans pour ng-src dans AngularJS

106

J'ai des images qui ressemblent à <img ng-src="dynamically inserted url"/>. Lorsqu'une seule image est chargée, je dois appliquer la méthode iScroll refresh () pour que l'image puisse faire défiler.

Quelle est la meilleure façon de savoir quand une image est complètement chargée pour exécuter un rappel?

Sergueï Basharov
la source
1
Jetez un œil à $ http Response Interceptors . Vous pouvez l'utiliser pour enregistrer un rappel lorsque la promesse se résout
Mark Meyer

Réponses:

185

Voici un exemple comment appeler l'image onload http://jsfiddle.net/2CsfZ/2/

L'idée de base est de créer une directive et de l'ajouter en tant qu'attribut à la balise img.

JS:

app.directive('imageonload', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                alert('image is loaded');
            });
            element.bind('error', function(){
                alert('image could not be loaded');
            });
        }
    };
});

HTML:

 <img ng-src="{{src}}" imageonload />
Mikach
la source
1
qu'en est-il d'un rappel d'échec?
Oleg Belousov
3
Et l'image progressive?
Nguyễn Đức Long
148

J'ai un peu modifié ceci pour que les $scopeméthodes personnalisées puissent être appelées:

<img ng-src="{{src}}" imageonload="doThis()" />

La directive:

.directive('imageonload', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind('load', function() {
                    //call the function that was passed
                    scope.$apply(attrs.imageonload);
                });
            }
        };
    })

J'espère que quelqu'un le trouvera TRÈS utile. Merci @mikach

La doThis()fonction serait alors une méthode $ scope

Peter
la source
3
C'est correct. La solution de Mikach n'a pas fonctionné pour moi jusqu'à ce que j'utilise $ apply () comme vous l'avez fait.
Jeremy Thille
C'est la meilleure des réponses fournies. Élimine totalement le besoin de tout chargement JQUERY.
Noel Baron
Merci d'avoir mis des points-virgules pour que les peluches n'explosent pas.
richard
cela me donne cette erreur: code.angularjs.org/1.4.9/docs/error/$rootScope/…
Paulo Roberto Rosa
9

@ Oleg Tikhonov: Je viens de mettre à jour le code précédent .. @ mikach Merci ..)

app.directive('imageonload', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        element.bind('load', function() {
            alert('image is loaded');
        });
        element.bind('error', function(){
             alert('image could not be loaded');
        });
    }
  };
});
Kailash
la source
1
Il vaudrait peut-être mieux avoir cela dans une directive «imageonerror» afin que vous puissiez effectuer une action différente.
Jon Catmull
5

Ma réponse:

 var img = new Image();
 var imgUrl = "path_to_image.jpg";
 img.src = imgUrl;
 img.onload = function () {
      $scope.pic = img.src;
 }
Rodrigo Andrade
la source
exactement ce que je cherchais!
Zohab Ali
4

Je viens de mettre à jour le code précédent.

<img ng-src="{{urlImg}}" imageonload="myOnLoadImagenFunction">

et directive ...

    .directive('imageonload', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind('load', function() {
                    scope.$apply(attrs.imageonload)(true);
                });
                element.bind('error', function(){
                  scope.$apply(attrs.imageonload)(false);
                });
            }
        };
    })
Ramiro Espagne
la source
0

En gros, c'est la solution que j'ai fini par utiliser.

$ apply () ne doit être utilisé par des sources externes que dans les bonnes circonstances.

plutôt que d'utiliser apply, j'ai jeté la mise à jour de la portée à la fin de la pile d'appels. Fonctionne aussi bien que "scope. $ Apply (attrs.imageonload) (true);".

window.app.directive("onImageload", ["$timeout", function($timeout) {

    function timeOut(value, scope) {
        $timeout(function() {
            scope.imageLoaded = value;
        });
    }

    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                timeOut(true, scope);
            }).bind('error', function() {
                timeOut(false, scope);
            });
        }
    };

}]);
Doug
la source
qu'entendez-vous par « $apply()ne doit être utilisé que par des sources externes»? je ne suis pas.
Genuinefafa
@g Genuinefafa Ce qu'il entend par «sources externes» est du code non angulaire. Ainsi, par exemple, si vous utilisez un écouteur d'événements JS générique pour appeler du code qui change $ scope, vous devrez utiliser $ apply ici. Mais s'il s'agit d'un événement Angular ou d'une fonction $ scope, vous n'avez pas besoin de $ apply car le cycle $ digest s'exécute déjà à partir de méthodes Angular.
tpartee