Если путь ngSrc разрешается до 404, существует ли способ отступить к умолчанию?
Приложение, которое я создаю, требует, чтобы мой пользователь установил 4 части информации, прежде чем этот образ даже получит возможность загрузки. Это изображение является центральным элементом приложения, поэтому сломанная ссылка на изображение делает его похожим на все, что угодно. Я хотел бы, чтобы другое изображение заняло свое место на 404.
Любые идеи? Я хотел бы избежать написания пользовательской директивы для этого.
Я был удивлен, что я не мог найти аналогичный вопрос, особенно когда первый вопрос в документах является одним и тем же!
http://docs.angularjs.org/api/ng.directive:ngSrc
Ответы
Ответ 1
Это довольно простая директива для просмотра ошибки загрузки изображения и замены 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);
}
});
}
}
});
Если вы хотите отобразить изображение ошибки, когда ngSrc пуст, вы можете добавить этот (Plunker):
attrs.$observe('ngSrc', function(value) {
if (!value && attrs.errSrc) {
attrs.$set('src', attrs.errSrc);
}
});
Проблема заключается в том, что ngSrc не обновляет атрибут src, если значение пустое.
Ответ 2
Немного поздно вечеринке, хотя я придумал решение более или менее той же проблемы в системе, которую я создаю.
Моя идея заключалась, однако, в том, чтобы обрабатывать EVERY image img
тег глобально.
Мне не нужно было перенести мои HTML
с помощью ненужных директив, таких как показанные здесь err-src
. Довольно часто, особенно с динамическими изображениями, вы не будете знать, хватит ли его, пока не станет слишком поздно. Добавление дополнительных директив на случайный шанс отсутствует, кажется, излишним для меня.
Вместо этого я расширяю существующий тег img
, который действительно является директивой Angular.
Итак - вот что я придумал.
Примечание. Для этого требуется наличие полной библиотеки JQuery, а не только JQlite Angular, потому что мы используем .error()
Вы можете увидеть это в действии на этом Plunker
Директива выглядит примерно так:
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');
});
}
}
});
При возникновении ошибки (которая будет вызвана тем, что изображение не существует или недоступно и т.д.), мы фиксируем и реагируем. Вы также можете попытаться получить размеры изображений - если они были в основном на изображении/стиле. Если нет, установите для себя значение по умолчанию.
В этом примере используется placehold.it вместо изображения.
Теперь КАЖДЫЙ образ, независимо от использования src
или ng-src
, сам покрыт, если ничего не загружается...
Ответ 3
Чтобы расширить решение Jason, чтобы уловить оба случая ошибки загрузки или пустую строку источника, мы можем просто добавить часы.
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);
}
}
});
Ответ 4
App.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;
});
}
};
});
в HTML:
<img class="img-circle" check-image ng-src="{{item.profileImg}}" />
Ответ 5
Если изображение равно 404, или изображение пустым, все, что не требуется директивам, вы можете просто использовать фильтр ng-src следующим образом:)
<img ng-src="{{ p.image || 'img/no-image.png' }}" />
Ответ 6
Я использую что-то вроде этого, но он предполагает, что команда .logo действительна. Он отключает значение по умолчанию, если команда team.logo не установлена или пуста.
<img ng-if="team.logo" ng-src="https://api.example.com/images/{{team.logo}}">
<img ng-hide="team.logo" ng-src="img/default.png">
Ответ 7
Для этого вам не нужен angular или даже CSS или JS. Если вы хотите, вы можете обернуть этот ответ (связанный) в простой директиве, чтобы сделать его проще, например или что-то, но это довольно простой процесс... просто оберните его в тег объекта...
Как скрыть изображение сломанной Icon, используя только CSS/HTML (без js)
Ответ 8
Есть ли конкретная причина, по которой вы не можете объявить резервное изображение в своем коде?
Как я понимаю, у вас есть два возможных случая для вашего источника изображения:
- Правильно установить фрагменты информации < 4 = Обратное изображение.
- Правильно установить фрагменты информации == 4 = Сгенерированный URL.
Я думаю, что это должно быть обработано вашим приложением - если правильный URL-адрес в настоящее время не может быть определен, вместо этого передайте URL-адрес загружаемого/резервного/placeholder-изображения.
Мысль о том, что у вас никогда не было "отсутствующего" изображения, потому что вы явно указали правильный URL-адрес для отображения в любой момент времени.
Ответ 9
Я предлагаю вам использовать директиву Angular UI Utils 'if statement' для решения вашей проблемы, как показано на http://angular-ui.github.io/. Я только что использовал его, чтобы сделать то же самое.
Это не проверено, но вы можете сделать что-то вроде:
Код контроллера:
$scope.showImage = function () {
if (value1 && value2 && value3 && value4) {
return true;
} else {
return false;
}
};
(или проще)
$scope.showImage = function () {
return value1 && value2 && value3 && value4;
};
HTML в представлении: <img ui-if="showImage()" ng-src="images/{{data.value}}.jpg" />
Или даже проще, вы можете просто использовать свойство scope:
Код контроллера:
$scope.showImage = value1 && value2 && value3 && value4;
HTML в виде: <img ui-if="showImage" ng-src="images/{{data.value}}.jpg" />
Для изображения с заполнителем просто добавьте еще один похожий тег <img>
, но добавьте параметр ui-if
с восклицательным знаком (!
) и сделайте ngSrc имеющим путь к образцу-заполнителю или просто используйте src
в соответствии с нормальным OL 'HTML.
например. <img ui-if="!showImage" src="images/placeholder.jpg" />
Очевидно, что все приведенные выше примеры кода предполагают, что каждый из значений 1, value2, value3 и value4 будет равен null
/false
, когда каждый из ваших 4 частей информации будет неполным (и, следовательно, также булевым значение true
, когда они завершены).
PS. Недавно проект AngularUI был разбит на подпроекты, и в настоящее время отсутствует документация для ui-if
(вероятно, в пакете есть). Тем не менее, это довольно просто использовать, как вы можете видеть, и я зарегистрировал проблему Github в проекте Angular UI, чтобы указать его команде.
UPDATE: "ui-if" отсутствует в проекте AngularUI, потому что он интегрирован в основной код AngularJS! Только с v1.1.x, хотя в настоящее время он помечен как "нестабильный".
Ответ 10
Вот решение, которое я придумал, используя собственный javascript. Я проверяю, если изображение сломано, а затем добавьте класс к изображению на всякий случай и изменив исходный код.
Я получил часть ответа из ответа 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';
};
}
}
});
Ответ 11
Придумал мое собственное решение.
Он заменяет изображение, если src или ngSrc пуст, и если img возвращает 404.
(fork решения @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);
}
}
}
});
Ответ 12
Это позволит только дважды зацикливать, чтобы проверить, не существует ли ng-src else, использовать err-src, это предотвращает цикл цикла.
(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);
}
});
}
}
}
})();