Angular的ng-src保留了之前的模型,直到它在内部预加载图像。我在每个页面上使用不同的图像作为横幅,当我切换路径时,我更改主视图,保持标题视图不变,只是在我拥有它时更改bannerUrl模型。
这会导致在加载新横幅图像时看到上一个横幅图像。
我很惊讶,目前尚无指令,但我想在尝试构建之前进行讨论。
我想做什么我认为自定义属性上有横幅模型。像:
<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}">
然后$ scope.watch for bannerUrl更改,并且一改变,首先用loader spinner替换ng-src,然后创建temproary img dom元素,从preload-src预加载图像,然后将其分配给preloadUrl。 / p>
例如,需要考虑如何为画廊处理多个图像。
有人对此有任何意见吗?或者有人可以指出我现有的代码?
我在github上看到了使用background-image的现有代码 - 但这对我不起作用,因为我需要动态高度/宽度,因为我的应用程序是响应式的,我不能用背景图像来做。
谢谢
答案 0 :(得分:48)
指令上的2个网址似乎过于复杂。我认为更好的是编写一个类似于:
的指令<img ng-src="{{bannerUrl}}" spinner-on-load />
该指令可以观察ng-src
和(例如)使用微调器设置visibility:false,直到图像加载完毕。如下所示:
scope: {
ngSrc: '='
},
link: function(scope, element) {
element.on('load', function() {
// Set visibility: true + remove spinner overlay
});
scope.$watch('ngSrc', function() {
// Set visibility: false + inject temporary spinner overlay
});
}
这样,该元素的行为非常类似于具有ng-src
属性的标准img,只需要用一些额外的行为进行操作。
答案 1 :(得分:24)
如果有人有兴趣,这是我的最终解决方案:我使用twitter bootstrap。因此,为所有图像添加了“淡入淡出”类,只需将指令切换为“in”,并在加载图像时淡入淡出
angular.module('myApp').directive('imgPreload', ['$rootScope', function($rootScope) {
return {
restrict: 'A',
scope: {
ngSrc: '@'
},
link: function(scope, element, attrs) {
element.on('load', function() {
element.addClass('in');
}).on('error', function() {
//
});
scope.$watch('ngSrc', function(newVal) {
element.removeClass('in');
});
}
};
}]);
<img img-preload class="fade" ng-src="{{imgSrc}}">
工作示例:http://ishq.org
答案 2 :(得分:3)
如果您愿意,可以将图像失败和图像加载器作为指令的属性传递....
myApp.directive("mySrc", function() {
return {
link: function(scope, element, attrs) {
var img, loadImage;
var IMAGE_LOAD="123.jpg";
var IMAGE_FAIL="123.jpg";
img = null;
loadImage = function() {
element[0].src = IMAGE_LOAD;
img = new Image();
img.src = attrs.mySrc;
img.onload = function() {
element[0].src = attrs.mySrc;
};
img.onerror=function ()
{
element[0].src = IMAGE_FAIL;
}
};
loadImage();
}
};
});
答案 3 :(得分:2)
我认为这可能是最优雅的解决方案,因为该指令实际上创建了微调器并自动将其删除:
app.directive('spinnerLoad', [function spinnerLoad() {
return {
restrict: 'A',
link: function spinnerLoadLink(scope, elem, attrs) {
scope.$watch('ngSrc', function watchNgSrc() {
elem.hide();
elem.after('<i class="fa fa-spinner fa-lg fa-spin"></i>'); // add spinner
});
elem.on('load', function onLoad() {
elem.show();
elem.next('i.fa-spinner').remove(); // remove spinner
});
}
};
}]);
这是html:
<img ng-src='{{imgUrl}}' spinner-load />
注意:您需要使用font-awesome才能按照此处的说明进行操作
答案 4 :(得分:1)
只是为了分享^^
//css
.media-box{
position: relative;
width:220px;
height: 220px;
overflow: hidden;
}
.media-box div{
position: absolute;
left: 0;
top: 0;
}
.spinner{
position: absolute;
left: 0;
top: 0;
background: #CCC url(./spinner.gif) no-repeat center center;
display: block;
width:220px;
height: 220px;
}
.feed img.spinner-show{
visibility: visible;
}
.feed img.spinner-hide{
visibility: hidden;
}
//html
<div class="media-box">
<div>
<img data-ng-src="{{item.media}}" alt="" title="" data-spinner-on-load>
</div>
</div>
//js
.directive('spinnerOnLoad', function() {
return {
restrict: 'A',
link: function(scope,element){
element.on('load', function() {
element.removeClass('spinner-hide');
element.addClass('spinner-show');
element.parent().find('span').remove();
});
scope.$watch('ngSrc', function() {
element.addClass('spinner-hide');
element.parent().append('<span class="spinner"></span>');
});
}
}
});
答案 5 :(得分:1)
而不是使用
element.on('load', function() {});
使用imagesLoaded插件。它会大大加快您的图像速度。
所以最终的代码是:
link: function(scope, element) {
imagesLoaded(element, function() {
});
scope.$watch('ngSrc', function() {
});
}
答案 6 :(得分:0)
我有这个指令,当img-src改变时显示一个微调器:
<img-with-loading
img-src="{{src}}"
spinner-class="{{spinnerClass}}"
/>
答案 7 :(得分:0)
可以使用image-preloader工厂在路线更改时预先加载图像并解决:
// call REST
return getContent.get().$promise.then(function(response) {
//return response;
// preload images from response
var imageLocations = [
// put image(s) from response to array
response.PostImage.big[0],
];
// check do we have (all) image(s) in array
console.log(imageLocations);
// return when all images are preloaded
return preloader.preloadImages( imageLocations )
.then(function() {
//if it was success
return response;
},
function() {
//if it failed
return response;
});
});
在这里完成教程: https://www.coditty.com/code/angular-preload-images-on-route-change-by-using-resolve
答案 8 :(得分:-1)
我发现一个简单的解决方案是在为其分配新值之前将网址更改为“//:0”
$scope.bannerUrl = 'initial value';
// When we want to change it
$scope.bannerUrl = '//:0'; // remove the previous img so it's not visible while the new one loads
$scope.bannerUrl = scope.preloadedUrl