Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Preload background image?

I have this angular project where I have a big background image that fills the page and a simple sidebar with links that when clicked, will change the url of the background with another image (from a cdn). Since these images are fairly big they take a second or two to load and it's noticeable, I want to add a preloader but I'm not sure how that would be done in angular 2.

In my html I have this:

<section class="fullsizebg image-bg" [ngStyle]="{'background-image': 'url(' + urlImage + ')'}"></section>

The variable urlImage is populated in the constructor of the component and the sidebar links changes the value of it on click with a simple function like so:

generateImage(data: any){
    this.urlImage = 'http://example.com/mycdn/'+this.data.url+'.jpg';
}

So the url is in fact changed instantly but the image takes a bit to load. I'd like to add a loading gif or something like that to keep the image change smooth to the user and not jumpy like it is now.

like image 207
Elaine Marley Avatar asked Sep 23 '16 08:09

Elaine Marley


2 Answers

One way to do it would be to use Blob to get the image and store it in an img component, this way you have your hands on the loading process and you can add your loading gif:

@Component({
   selector:'loading-image',
   template:'<img alt="foo" [src]="src"/>'
})
export class ExampleLoadingImage{

   public src:string = "http://example.com/yourInitialImage.png";

   constructor(private http:Http){}

   generateImage(data: any): void {
      this.src = 'http://www.downgraf.com/wp-content/uploads/2014/09/01-progress.gif'; //Just a random loading gif found on google.
      this.http.get('http://example.com/mycdn/'+this.data.url+'.jpg')
         .subscribe(response => {
            let urlCreator = window.URL;
            this.src = urlCreator.createObjectURL(response.blob());
         });
    }
}

N.B: You should type your data parameter, typing is a good way to ensure consistency over your code, any should only be used as a joker, like Object in Java.

like image 193
Supamiu Avatar answered Oct 10 '22 03:10

Supamiu


This solution leverages what angular and the browser already provide. The image loading is done by the browser and there's no need to mess with any data or the DOM yourself.

I have tested this on Chrome 53 and it's working flawlessly.

This is your element, that's getting its background changed:

<div class="yourBackgroundClass" [style.background-image]="'url(' + imgUrl + ')'"></div>

To prefetch the image, we use an image tag, that is not shown. It'd be good to additionally make its position: absolute and move it out of the view or make it really tiny, so that it can't interfere with your actual content.

<img [src]="imgPreloadUrl" (load)="imgUrl = imgPreloadUrl" hidden>

Through setting imgPreloadUrl, the img's src is updated by angular and the browser loads the image into the invisible img tag. Once it's done, onload fires and we set imgUrl = imgPreloadUrl. Angular now updates style.background-image of the actual background and the background image switches immediately, because it's already loaded in the hidden image.

While imgUrl !== imgPreloadUrl we can show a spinner to indicate loading:

<div class="spinner" *ngIf="imgUrl !== imgPreloadUrl"></div>

test with:

<button (click)="imgPreloadUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/24/Willaerts_Adam_The_Embarkation_of_the_Elector_Palantine_Oil_Canvas-huge.jpg'">test</button>
like image 32
j2L4e Avatar answered Oct 10 '22 02:10

j2L4e