Evento carregado de imagem em para ng-src em AngularJS

106

Tenho imagens parecidas <img ng-src="dynamically inserted url"/>. Quando uma única imagem é carregada, preciso aplicar o método iScroll refresh () para tornar a imagem rolável.

Qual é a melhor maneira de saber quando uma imagem está totalmente carregada para executar algum retorno de chamada?

Sergei Basharov
fonte
1
Dê uma olhada em $ http Response Interceptors . Você pode usar isso para registrar um retorno de chamada quando a promessa for resolvida
Mark Meyer

Respostas:

185

Aqui está um exemplo de como chamar onload de imagem http://jsfiddle.net/2CsfZ/2/

A ideia básica é criar uma diretiva e adicioná-la como atributo à tag 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
fonte
1
que tal um retorno de chamada de falha?
Oleg Belousov de
3
E a imagem progressiva?
Nguyễn Đức Long
148

Eu modifiquei um pouco para que os $scopemétodos personalizados possam ser chamados:

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

A diretiva:

.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);
                });
            }
        };
    })

Espero que alguém ache MUITO útil. Obrigado @mikach

A doThis()função seria então um método $ scope

Peter
fonte
3
Está correto. A solução de Mikach não funcionou para mim até que usei $ apply () como você fez.
Jeremy Thille de
Esta é a melhor das respostas fornecidas. Elimina totalmente a necessidade de qualquer carregamento JQUERY também.
Noel Baron
Obrigado por colocar um ponto e vírgula para que o fiapo não explodisse.
richard
isso me dá este erro: code.angularjs.org/1.4.9/docs/error/$rootScope/…
Paulo Roberto Rosa
9

@ Oleg Tikhonov: Acabei de atualizar o código anterior .. @ mikach Obrigado ..)

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
fonte
1
Pode ser melhor ter isso em uma diretiva 'imageonerror' para que você possa executar uma ação diferente.
Jon Catmull
4

Acabei de atualizar o código anterior ..

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

e diretiva ...

    .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 Espanha
fonte
4

Minha resposta:

 var img = new Image();
 var imgUrl = "path_to_image.jpg";
 img.src = imgUrl;
 img.onload = function () {
      $scope.pic = img.src;
 }
Rodrigo Andrade
fonte
Exatamente o que eu estava procurando!
Zohab Ali
0

Basicamente, essa é a solução que acabei usando.

$ apply () só deve ser usado por fontes externas nas circunstâncias certas.

em vez de usar apply, lancei a atualização de escopo para o final da pilha de chamadas. Funciona tão bem quanto "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
fonte
o que você quer dizer com " $apply()só deve ser usado por fontes externas"? eu não estou acompanhando.
genuínofafa
@genuinefafa O que ele quer dizer com 'fontes externas' é código não angular. Então, por exemplo, se você estiver usando um ouvinte de evento JS genérico para chamar o código que altera $ escopo, você precisaria usar $ apply lá. Mas se for um evento Angular ou uma função $ scope, você não precisa de $ apply porque o ciclo $ digest já está sendo executado a partir de métodos Angular.
tpartee de