我正在构建的应用程序要求我的用户在此图像甚至有机会加载之前设置 4 条信息。该图像是应用程序的核心部分,因此损坏的图像链接使它看起来像是整个事情都被破坏了。我想让另一个图像在 404 上取代它。
有任何想法吗?我想避免为此编写自定义指令。
我很惊讶我找不到类似的问题,尤其是当文档中的第一个问题是同一个问题时!
我正在构建的应用程序要求我的用户在此图像甚至有机会加载之前设置 4 条信息。该图像是应用程序的核心部分,因此损坏的图像链接使它看起来像是整个事情都被破坏了。我想让另一个图像在 404 上取代它。
有任何想法吗?我想避免为此编写自定义指令。
我很惊讶我找不到类似的问题,尤其是当文档中的第一个问题是同一个问题时!
这是一个非常简单的指令,用于监视加载图像的错误并替换 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 属性。
虽然我想出了一个解决方案来解决我正在构建的系统中或多或少相同的问题。
不过,我的想法是在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
已经覆盖,以防万一没有加载......
要扩展 Jason 解决方案以捕获加载错误或空源字符串的两种情况,我们只需添加一个 watch。
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);
}
}
});
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}}" />
如果图像为 404 或图像为空,则无论不需要指令,您都可以像这样简单地使用 ng-src 过滤器:)
<img ng-src="{{ p.image || 'img/no-image.png' }}" />
我使用类似的东西,但它假设 team.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">
你不需要 Angular,甚至 CSS 或 JS。如果你愿意,你可以将这个答案(链接)包装在一个简单的指令中,以使其更简单,比如或其他东西,但这是一个非常简单的过程......只需将它包装在一个对象标签中......
是否有特定原因不能在代码中声明后备图像?
据我了解,您的图像源有两种可能的情况:
我认为这应该由您的应用程序处理 - 如果当前无法确定正确的 URL,则传递加载/后备/占位符图像 URL。
原因是您永远不会有“丢失”图像,因为您已明确声明要在任何时间点显示的正确 URL。
我建议您可能喜欢使用 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.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" />
显然,上述所有代码示例都假设 value1、value2、value3 和 value4 中的每一个都等于null
/false
当您的 4 条信息中的每一条都不完整时(因此也等于true
它们完整时的布尔值)。
PS。AngularUI 项目最近被分解为子项目,ui-if
目前似乎缺少文档(虽然它可能在某个包中)。但是,如您所见,它使用起来非常简单,我在 Angular UI 项目上记录了一个 Github 的“问题”,也向团队指出了这一点。
更新:AngularUI 项目中缺少“ui-if”,因为它已集成到核心 AngularJS 代码中!仅从 v1.1.x 开始,目前被标记为“不稳定”。
这是我使用本机 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';
};
}
}
});
这将只允许循环两次,以检查 ng-src 是否不存在,否则使用 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);
}
});
}
}
}
})();
想出了我自己的解决方案。如果 src 或 ngSrc 为空,并且如果 img 返回 404,它将替换 image。
(@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);
}
}
}
});