Aplikacja, którą tworzę, wymaga od mojego użytkownika ustawienia 4 informacji, zanim ten obraz będzie miał szansę się załadować. Ten obraz jest centralnym elementem aplikacji, więc uszkodzony link do obrazu sprawia, że wygląda na to, że wszystko jest zepsute. Chciałbym, aby inny obraz zajął jego miejsce na 404.
Jakieś pomysły? Chciałbym uniknąć pisania niestandardowej dyrektywy w tym zakresie.
Byłem zaskoczony, że nie mogłem znaleźć podobnego pytania, zwłaszcza gdy pierwsze pytanie w dokumentach jest takie samo!
angularjs
angularjs-directive
will_hardin
źródło
źródło
Odpowiedzi:
Jest to dość prosta dyrektywa, aby obserwować błąd podczas ładowania obrazu i zastąpić src. (Plunker)
HTML:
<img ng-src="smiley.png" err-src="http://google.com/favicon.ico" />
JavaScript:
var app = angular.module("MyApp", []); app.directive('errSrc', function() { return { link: function(scope, element, attrs) { element.bind('error', function() { if (attrs.src != attrs.errSrc) { attrs.$set('src', attrs.errSrc); } }); } } });
Jeśli chcesz wyświetlić obraz błędu, gdy ngSrc jest pusty, możesz dodać to (Plunker) :
attrs.$observe('ngSrc', function(value) { if (!value && attrs.errSrc) { attrs.$set('src', attrs.errSrc); } });
Problem polega na tym, że ngSrc nie aktualizuje atrybutu src, jeśli wartość jest pusta.
źródło
src
atrybutu dlaerr-src
obrazu: plnkr.co/edit/b05WtghBOHkxKdttZ8q5Trochę późno na imprezę, chociaż wpadłem na rozwiązanie mniej więcej tego samego problemu w systemie, który buduję.
Moim pomysłem było jednak obsłużyć KAŻDY
img
tag graficzny na całym świecie.Nie chciałem obciążać mnie
HTML
niepotrzebnymi dyrektywami, takimi jakerr-src
te pokazane tutaj. Dość często, zwłaszcza w przypadku dynamicznych obrazów, nie wiadomo, czy brakuje, aż będzie za późno. Dodawanie dodatkowych dyrektyw w przypadku braku obrazu wydaje mi się przesadą.Zamiast tego rozszerzam istniejący
img
tag - o to tak naprawdę chodzi w dyrektywach Angulara.A więc - oto co wymyśliłem.
Uwaga : Wymaga to obecności pełnej biblioteki JQuery, a nie tylko JQlite Angular, ponieważ używamy
.error()
Możesz zobaczyć to w akcji w tym Plunkerze
Dyrektywa wygląda mniej więcej tak:
app.directive('img', function () { return { restrict: 'E', link: function (scope, element, attrs) { // show an image-missing image element.error(function () { var w = element.width(); var h = element.height(); // using 20 here because it seems even a missing image will have ~18px width // after this error function has been called if (w <= 20) { w = 100; } if (h <= 20) { h = 100; } var url = 'http://placehold.it/' + w + 'x' + h + '/cccccc/ffffff&text=Oh No!'; element.prop('src', url); element.css('border', 'double 3px #cccccc'); }); } } });
Gdy wystąpi błąd (który będzie spowodowany tym, że obraz nie istnieje lub jest nieosiągalny itp.) Przechwytujemy i reagujemy. Możesz też spróbować uzyskać rozmiary obrazu - jeśli były obecne na obrazku / stylu w pierwszej kolejności. Jeśli nie, ustaw siebie jako domyślną.
W tym przykładzie zamiast obrazu wyświetlany jest obraz placehold.it.
Teraz KAŻDY obraz, niezależnie od tego,
src
czyng-src
został użyty, czy też został zakryty na wypadek, gdyby nic się nie załadowało ...źródło
Aby rozwinąć rozwiązanie Jasona w celu wychwycenia obu przypadków błędu ładowania lub pustego ciągu źródłowego, możemy po prostu dodać zegarek.
HTML:
<img ng-src="smiley.png" err-src="http://google.com/favicon.ico" />
JavaScript:
var app = angular.module("MyApp", []); app.directive('errSrc', function() { return { link: function(scope, element, attrs) { var watcher = scope.$watch(function() { return attrs['ngSrc']; }, function (value) { if (!value) { element.attr('src', attrs.errSrc); } }); element.bind('error', function() { element.attr('src', attrs.errSrc); }); //unsubscribe on success element.bind('load', watcher); } } });
źródło
ng-if
w szablonie (pusty ciąg src)attrs.$observe('ngSrc', function(value) {...});
, to jest to, czego używa ngSrc wewnętrznie zamiast $ watchApp.directive('checkImage', function ($q) { return { restrict: 'A', link: function (scope, element, attrs) { attrs.$observe('ngSrc', function (ngSrc) { var deferred = $q.defer(); var image = new Image(); image.onerror = function () { deferred.resolve(false); element.attr('src', BASE_URL + '/assets/images/default_photo.png'); // set default image }; image.onload = function () { deferred.resolve(true); }; image.src = ngSrc; return deferred.promise; }); } }; });
w HTML:
<img class="img-circle" check-image ng-src="{{item.profileImg}}" />
źródło
Jeśli obraz jest 404 lub obraz jest pusty, cokolwiek nie jest potrzebne dyrektyw, możesz po prostu użyć filtru ng-src w ten sposób :)
<img ng-src="{{ p.image || 'img/no-image.png' }}" />
źródło
Używam czegoś takiego, ale zakładam, że logo team.logo jest prawidłowe. Wymusza ustawienie domyślne, jeśli „team.logo” nie jest ustawione lub jest puste.
<img ng-if="team.logo" ng-src="https://api.example.com/images/{{team.logo}}"> <img ng-hide="team.logo" ng-src="img/default.png">
źródło
Nie potrzebujesz do tego angulara ani nawet CSS czy JS. Jeśli chcesz, możesz zawinąć tę odpowiedź (połączoną) w prostą dyrektywę, aby ją uprościć, na przykład lub coś w tym stylu, ale jest to dość prosty proces ... po prostu zawiń go w znacznik obiektu ...
Jak ukryć uszkodzoną ikonę obrazu, używając tylko CSS / HTML (bez js)
źródło
Czy istnieje konkretny powód, dla którego nie możesz zadeklarować obrazu zastępczego w swoim kodzie?
Jak rozumiem, masz dwa możliwe przypadki źródła obrazu:
Myślę, że powinna to obsługiwać Twoja aplikacja - jeśli obecnie nie można określić prawidłowego adresu URL, zamiast tego podaj adres URL obrazu wczytywania / zastępczego / zastępczego.
Powodem jest to, że nigdy nie masz „brakującego” obrazu, ponieważ wyraźnie zadeklarowałeś poprawny adres URL do wyświetlenia w dowolnym momencie.
źródło
Sugeruję, abyś mógł skorzystać z dyrektywy „if statement” w narzędziach Angular UI Utils, aby rozwiązać problem, którą można znaleźć na stronie http://angular-ui.github.io/ . Właśnie użyłem go, aby zrobić dokładnie to samo.
To nie jest testowane, ale możesz zrobić coś takiego:
Kod kontrolera:
$scope.showImage = function () { if (value1 && value2 && value3 && value4) { return true; } else { return false; } };
(lub prostsze)
$scope.showImage = function () { return value1 && value2 && value3 && value4; };
HTML w widoku:
<img ui-if="showImage()" ng-src="images/{{data.value}}.jpg" />
Lub jeszcze prościej, możesz po prostu użyć właściwości zakresu:
Kod kontrolera:
$scope.showImage = value1 && value2 && value3 && value4;
HTML w widoku:
<img ui-if="showImage" ng-src="images/{{data.value}}.jpg" />
W przypadku obrazu zastępczego wystarczy dodać kolejny podobny
<img>
znacznik, ale poprzedzićui-if
parametr!
znakiem wykrzyknika ( ) i albo ustawić w ngSrc ścieżkę do obrazu zastępczego, albo po prostu użyćsrc
tagu, jak w zwykłym starym języku HTML.na przykład.
<img ui-if="!showImage" src="images/placeholder.jpg" />
Oczywiście wszystkie powyższe przykłady kodu zakładają, że każda z wartości 1, wartość2, wartość3 i wartość4 będzie równa się
null
/false
kiedy każda z 4 informacji jest niekompletna (a zatem także wartością logiczną,true
kiedy są kompletne).PS. Projekt AngularUI został niedawno podzielony na podprojekty, a dokumentacji
ui-if
wydaje się, że obecnie brakuje (prawdopodobnie jest ona gdzieś w pakiecie). Jest jednak dość prosty w użyciu, jak widać, i zarejestrowałem „problem” na Github w projekcie Angular UI, aby wskazać go zespołowi.AKTUALIZACJA: w projekcie AngularUI brakuje „ui-if”, ponieważ zostało ono zintegrowane z podstawowym kodem AngularJS! Jednak tylko od wersji 1.1.x, która jest obecnie oznaczona jako „niestabilna”.
źródło
ng-if
zrobiłem to w rdzeniu przy okazji (od 1.1.5, jeśli się nie mylę).Oto rozwiązanie, które wymyśliłem, używając natywnego javascript. Sprawdzam, czy obraz jest uszkodzony, a następnie na wszelki wypadek dodaję klasę do obrazu i zmieniam źródło.
Część mojej odpowiedzi pochodzi z odpowiedzi Quora http://www.quora.com/How-do-I-use-JavaScript-to-find-if-an-image-is-broken
app.directive('imageErrorDirective', function () { return { restrict: 'A', link: function (scope, element, attrs) { element[0].onerror = function () { element[0].className = element[0].className + " image-error"; element[0].src = 'http://img3.wikia.nocookie.net/__cb20140329055736/pokemon/images/c/c9/702Dedenne.png'; }; } } });
źródło
Przyszło z moim własnym rozwiązaniem. Zastępuje obraz zarówno, jeśli src, jak i ngSrc jest puste, i jeśli img zwraca 404.
(widelec rozwiązania @Darren)
directive('img', function () { return { restrict: 'E', link: function (scope, element, attrs) { if((('ngSrc' in attrs) && typeof(attrs['ngSrc'])==='undefined') || (('src' in attrs) && typeof(attrs['src'])==='undefined')) { (function () { replaceImg(); })(); }; element.error(function () { replaceImg(); }); function replaceImg() { var w = element.width(); var h = element.height(); // using 20 here because it seems even a missing image will have ~18px width // after this error function has been called if (w <= 20) { w = 100; } if (h <= 20) { h = 100; } var url = 'http://placehold.it/' + w + 'x' + h + '/cccccc/ffffff&text=No image'; element.prop('src', url); } } } });
źródło
Pozwoli to tylko na dwukrotne zapętlenie, aby sprawdzić, czy ng-src nie istnieje, w przeciwnym razie użyj err-src, co zapobiega kontynuowaniu pętli.
(function () { 'use strict'; angular.module('pilierApp').directive('errSrc', errSrc); function errSrc() { return { link: function(scope, element, attrs) { element.error(function () { // to prevent looping error check if src == ngSrc if (element.prop('src')==attrs.ngSrc){ //stop loop here element.prop('src', attrs.errSrc); } }); } } } })();
źródło