我正在构建的应用程序要求用户设置4条信息,然后才能加载该图像。该图像是应用程序的核心,因此断开的图像链接使整个外观看起来很闷。我想在404上放另一张图片。
有任何想法吗?我想避免为此编写自定义指令。
令我惊讶的是,我找不到类似的问题,尤其是当文档中的第一个问题相同时!
我正在构建的应用程序要求用户设置4条信息,然后才能加载该图像。该图像是应用程序的核心,因此断开的图像链接使整个外观看起来很闷。我想在404上放另一张图片。
有任何想法吗?我想避免为此编写自定义指令。
令我惊讶的是,我找不到类似的问题,尤其是当文档中的第一个问题相同时!
Answers:
这是一个非常简单的指令,用于监视加载图像并替换src时的错误。 (插棒)
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()
该指令看起来非常像这样:
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解决方案以捕获加载错误或源字符串为空的两种情况,我们只需添加一个手表即可。
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的方式
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}}" />
如果image为404或image为null为空,则无需使用指令,您可以使用ng-src过滤器,例如:
<img ng-src="{{ p.image || 'img/no-image.png' }}" />
您不需要它,甚至不需要CSS或JS。如果需要,您可以将这个答案(链接的)包装在一个简单的指令中,使其变得更简单(如类似),但这是一个非常简单的过程...只需将其包装在一个对象标记中即可...
您是否有特定原因无法在代码中声明后备图片?
据我了解,您的图片来源有两种可能的情况:
我认为这应该由您的应用处理-如果当前无法确定正确的URL,请传递加载/后备/占位符图像URL。
原因是您永远不会有“丢失”的图像,因为您已经明确声明了可以在任何时间显示的正确URL。
我建议您可能希望使用Angular UI Utils的“ if语句”指令来解决您的问题,如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
按照常规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
使其成为核心btw(如果我没记错的话,从1.1.5开始)。
这是我使用本机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';
};
}
}
});
想出了自己的解决方案。如果src或ngSrc为空,并且img返回404,它将替换图像。
(@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);
}
}
}
});
这将只允许循环两次,以检查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);
}
});
}
}
}
})();