Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to preload images with Angular.js

Angular's ng-src keeps previous model until it preloads image internally. I am using different image for the banner on each page, when I switch routes, i change main view, leaving header view as it is, just changing bannerUrl model when I have it.

This is resulting in seeing previous banner image while new one is loading.

I was surprised that there's no directive for it yet, but I wanted to make a discussion before trying to build one.

What I want to do I think is have banner model on custom attribute. like:

<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}"> 

Then $scope.watch for bannerUrl change, and as soon as it changes, replace ng-src with loader spinner first, and then create temproary img dom element, preload image from preload-src and then assing it to preloadUrl.

Need to think how to handle multiple images too for galleries for example.

Does anyone have any input on it? or maybe someone can point me to existing code?

I've seen existing code on github that uses background-image - but that doesn't work for me as I need dynamic height/width as my app is responsive, and I cannot do it with background-image.

Thank you

like image 679
Yuri Avatar asked Jan 07 '14 23:01

Yuri


People also ask

How to preload images using preloader in JavaScript?

Initiate a variable preloaded to store the number of images loaded during the preloading phase and an array of images images to store the address of all the images to be preloaded. We define a function preLoader () to create image objects for all images that have to be preloaded and store the src property on the object the array images.

What is a preloader in angular?

Website Preloader using AngularJS Preloaders are small and lightweight animations that indicate to the end user that something is churning away at the back-end of the application, and that nothing is broke. They give assurance to the end user and helps them relax, especially if your preloader is something catchy and nice.

How to see the difference between preloading and dynamically-loaded image gallery?

To see the difference that preloading makes, you can inspect the same dynamically-loaded image gallery but with preloaded first image by following the steps from the first example. An alternative way to avoid the problem would be to use a markup-based carousel and have the browser's preloader pick up the required resources.

Why do some images have to be preloaded on a website?

These images will be loaded on the fly and would cause a delay in the display as the image downloads first. It makes a website look very bad, and hence these images must be preloaded.


2 Answers

Having the 2 urls on the directive seems a touch overcomplicated. What I think is better is to write a directive that works like:

<img ng-src="{{bannerUrl}}" spinner-on-load /> 

And the directive can watch ng-src and (for example) set visibility:false with a spinner until the image has loaded. So something like:

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   }); } 

This way the element behaves very much like a standard img with an ng-src attribute, just with a bit of extra behaviour bolted on.

http://jsfiddle.net/2CsfZ/47/

like image 168
Michal Charemza Avatar answered Sep 19 '22 11:09

Michal Charemza


If anyone is interested this is my final solution: I use twitter bootstrap. So added class of "fade" to all images and just toggling class "in" with directive to fade in and out when image is loaded

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}}"> 

Working example: http://ishq.org

like image 44
Yuri Avatar answered Sep 18 '22 11:09

Yuri