【发布时间】:2013-04-24 23:42:08
【问题描述】:
我正在构建的应用程序需要我的用户设置 4 条信息,然后才能加载此图像。该图像是应用程序的核心部分,因此损坏的图像链接使它看起来像是整个事情都被破坏了。我想让另一个图像在 404 上取代它。
有什么想法吗?我想避免为此编写自定义指令。
我很惊讶我找不到类似的问题,尤其是当文档中的第一个问题是同一个问题时!
【问题讨论】:
标签: angularjs angularjs-directive
我正在构建的应用程序需要我的用户设置 4 条信息,然后才能加载此图像。该图像是应用程序的核心部分,因此损坏的图像链接使它看起来像是整个事情都被破坏了。我想让另一个图像在 404 上取代它。
有什么想法吗?我想避免为此编写自定义指令。
我很惊讶我找不到类似的问题,尤其是当文档中的第一个问题是同一个问题时!
【问题讨论】:
标签: angularjs angularjs-directive
要扩展 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);
}
}
});
【讨论】:
ng-if 轻松检查的内容(空 src 字符串)似乎有点矫枉过正
attrs.$observe('ngSrc', function(value) {...});,这就是ngSrc在内部使用而不是$watch
这将只允许循环两次,以检查 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);
}
});
}
}
}
})();
【讨论】:
你不需要 Angular,甚至 CSS 或 JS。如果你愿意,你可以将这个答案(链接)包装在一个简单的指令中,以使其更简单,比如或其他东西,但这是一个非常简单的过程......只需将它包装在一个对象标签中......
How to hide image broken Icon using only CSS/HTML (without js)
【讨论】:
想出了我自己的解决方案。 如果 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);
}
}
}
});
【讨论】:
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}}" />
【讨论】:
这是我使用本机 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';
};
}
}
});
【讨论】:
如果图像为 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">
【讨论】:
虽然我想出了一个解决方案来解决我正在构建的系统中或多或少相同的问题。
不过,我的想法是在全局范围内处理每个图像 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,都已被覆盖,以防万一没有加载...
【讨论】:
这是一个非常简单的指令,用于监视加载图像的错误并替换 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 属性。
【讨论】:
err-src 图像使用src 属性:plnkr.co/edit/b05WtghBOHkxKdttZ8q5
我建议您可能喜欢使用 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 具有占位符图像的路径,或者只使用 @ 987654330@ 标记为正常的 ol' HTML。
例如。 <img ui-if="!showImage" src="images/placeholder.jpg" />
显然,当您的 4 条信息都不完整时,上述所有代码示例都假设 value1、value2、value3 和 value4 中的每一个都等于null / false(因此也等于一个布尔值true 的值(当它们完成时)。
PS。 AngularUI 项目最近被拆分为子项目,目前似乎缺少ui-if 的文档(虽然它可能在某个包中)。但是,如您所见,它使用起来非常简单,而且我在 Angular UI 项目上记录了一个 Github 的“问题”,也向团队指出了这一点。
更新:AngularUI 项目中缺少“ui-if”,因为它已集成到核心 AngularJS 代码中!仅从 v1.1.x 开始,目前被标记为“不稳定”。
【讨论】:
ng-if 进入核心顺便说一句(如果我没记错的话,从 1.1.5 开始)。
是否存在无法在代码中声明后备图像的特定原因?
据我了解,您的图片来源有两种可能的情况:
我认为这应该由您的应用处理 - 如果当前无法确定正确的 URL,请改为传递加载/后备/占位符图像 URL。
原因是您永远不会有“丢失”图像,因为您已明确声明要在任何时间点显示的正确 URL。
【讨论】: