[英]Best way to preload images with Angular.js
Angular的ng-src會保留先前的模型,直到它在內部預加載圖像為止。 我在每個頁面上的橫幅使用不同的圖像,當我切換路線時,我更改主視圖,保留標題視圖,只是在擁有它時更改bannerUrl模型。
這導致在加載新的橫幅圖像時看到先前的橫幅圖像。
令我驚訝的是,目前還沒有指令,但是我想在嘗試構建指令之前先進行討論。
我想做的是在自定義屬性上設置橫幅廣告模型。 喜歡:
<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}">
然后$ scope.watch更改bannerUrl,並在更改后立即用loader spinner替換ng-src,然后創建臨時img dom元素,從preload-src預加載圖像,然后將其關聯到preloadUrl。
例如,還需要考慮如何為畫廊處理多個圖像。
有人對此有意見嗎? 也許有人可以指出我現有的代碼?
我已經在github上看到了使用background-image的現有代碼-但這對我不起作用,因為我的應用程序具有響應能力,因此我需要動態的高度/寬度,而我無法使用background-image來實現。
謝謝
在指令上具有2個url似乎有點復雜。 我認為更好的是編寫一個像這樣的指令:
<img ng-src="{{bannerUrl}}" spinner-on-load />
並且該指令可以監視ng-src
並(例如)使用微調框設置可視性: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,只是附加了一些額外的行為。
如果有人感興趣,這是我的最終解決方案:我使用twitter bootstrap。 因此,向所有圖像添加了“淡入淡出”類,並且僅在加載圖像時使用指令切換“進入”類以淡入和淡出
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
如果需要,可以將圖像失敗和圖像加載器作為指令的屬性傳遞。
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();
}
};
});
我認為這可能是最優雅的解決方案,因為該指令實際上會創建微調器並自動將其刪除:
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 />
注意:您需要使用超贊的字體才能使它按此處所述工作
只是分享^^
//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>');
});
}
}
});
而不是使用
element.on('load', function() {});
使用imagesLoaded插件。 它將大大加快您的圖像速度。
所以最終的代碼將是:
link: function(scope, element) {
imagesLoaded(element, function() {
});
scope.$watch('ngSrc', function() {
});
}
我有這個指令,它在img-src更改時顯示一個微調器:
<img-with-loading
img-src="{{src}}"
spinner-class="{{spinnerClass}}"
/>
此處的代碼: http : //jsfiddle.net/ffabreti/yw74upyr/
可以使用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
我發現一個簡單的解決方案是在分配新值之前將url更改為“ //: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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.