Angular's ng-src conserve le modèle précédent jusqu'à ce qu'il précharge l'image en interne. J'utilise une image différente pour la bannière sur chaque page. Lorsque je change d'itinéraire, je change de vue principale, laissant la vue d'en-tête telle qu'elle est, changeant simplement le modèle de bannièreUrl quand je l'ai.
Cela entraîne l'affichage de la bannière précédente pendant le chargement de la nouvelle.
J'ai été surpris qu'il n'y ait pas encore de directive pour cela, mais je voulais faire une discussion avant d'essayer de la construire.
Je pense que ce que je veux faire, c'est avoir un modèle de bannière sur un attribut personnalisé. comme:
<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}">
Puis $ scope.watch pour le changement bannerUrl, et dès que cela change, remplacez d'abord ng-src par loader spinner, puis créez un élément img dom temproary, préchargez l'image à partir de preload-src, puis assignez-le à preloadUrl.
Vous devez également penser à la gestion de plusieurs images, par exemple pour les galeries.
Est-ce que quelqu'un a des commentaires à ce sujet? ou peut-être que quelqu'un peut m'indiquer le code existant?
J'ai vu du code existant sur github qui utilise background-image - mais cela ne fonctionne pas pour moi car j'ai besoin d'une hauteur/largeur dynamique car mon application est réactive, et je ne peux pas le faire avec background-image.
Je vous remercie
Avoir les 2 urls sur la directive semble un peu compliqué. Ce qui me semble préférable, c’est d’écrire une directive qui fonctionne comme:
<img ng-src="{{bannerUrl}}" spinner-on-load />
Et la directive peut regarder ng-src
et (par exemple) définir la visibilité: false avec un compteur jusqu'à ce que l'image soit chargée. Donc, quelque chose comme:
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
});
}
De cette façon, l’élément se comporte comme un img standard avec un attribut ng-src
, avec juste un comportement supplémentaire.
Si quelqu'un est intéressé, voici ma solution finale: j'utilise le bootstrap de Twitter. Donc ajouté classe de "fade" à toutes les images et juste basculer la classe "in" avec directive à fondu en entrée et en sortie lorsque l'image est chargée
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}}">
Exemple de travail: http://ishq.org
Si vous le souhaitez, vous pouvez transmettre l’échec et le chargeur d’image en tant qu’attributs de la directive ....
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();
}
};
});
Je pense que c'est peut-être la solution la plus élégante, car la directive crée effectivement le cône et le supprime automatiquement
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
});
}
};
}]);
Voici le code HTML:
<img ng-src='{{imgUrl}}' spinner-load />
Remarque: vous devrez utiliser font-awesome pour que cela fonctionne comme décrit ici.
À la place d'utiliser
element.on('load', function() {});
utilisez imagesLoaded plugin. Cela accélérera considérablement vos images.
Le code final serait donc:
link: function(scope, element) {
imagesLoaded(element, function() {
});
scope.$watch('ngSrc', function() {
});
}
Juste pour partager ^^
//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>');
});
}
}
});
J'ai cette directive qui montre un spinner quand img-src change:
<img-with-loading
img-src="{{src}}"
spinner-class="{{spinnerClass}}"
/>
Code ici: http://jsfiddle.net/ffabreti/yw74upyr/
les images peuvent être préchargées lors du changement de route à l’aide de image-preloader factory et résolvent:
// 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;
});
});
terminez le tutoriel ici: https://www.coditty.com/code/angular-preload-images-on-route-change-by-using-resolve