aFarkas / lazysizes

High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.
MIT License
17.52k stars 1.73k forks source link

Guide to use in angular #528

Closed RscAnonymous closed 5 years ago

RscAnonymous commented 6 years ago

Can you please provide a step by step guide on how to make it work in Angular 2+

aFarkas commented 6 years ago

everytime you set data-src/data-srcset make also sure to set the lazyload class.

or use the attr change plugin and remember to only change the data-src/data-srcset and not src/srcet directly.

LauraNavarroGalvan commented 5 years ago

I'm using Angular 7 and its worked for me in this way

  1. npm install lazysizes --save

  2. In my angular.json set in the scripts

    "scripts": [ "node_modules/lazysizes/lazysizes.min.js" ]

  3. change all the img tags for :

    <img class="lazyload" data-src="assets/img/Exp.jpg" >

johanchouquet commented 5 years ago

Hi,

  1. In addition to @LauraNavarroGalvan , i've tested that to add some plugins behaviors, you have to add the path to each plugin in the scripts array of .angular.json file.

  2. To use the wanted behaviours of plugins, you only have to set CSS classes in your html & css files.

  3. To exploit the events of the library, I personally use @HostListener in my components. Maybe there's a better approach or a more Angular way solution with Outputs.

@aFarkas , what's the prefered way according to you ?

dominicracine commented 5 years ago

Hey, I can't figure out how to configure lazySizes. I don't know what is the good way of doing this in anguar, but here's what I tried : First approach : ngOnInit() { window.lazySizesConfig = window.lazySizesConfig || {}; // use .lazy instead of .lazyload window.lazySizesConfig.lazyClass = 'lazy'; } Second approach : Also, I tried to put this script in file.js and import "scripts": [ "node_modules/lazysizes/plugins/rias/ls.rias.min.js", "node_modules/lazysizes/lazysizes.min.js", "src/assets/js/file.js" ] }, I can tell that the script is running, but it doesn't work when I use lazy instead of lazyload...

For more info, I'm trying to reproduce this code in angular

link : https://codepen.io/brianluk/pen/WBNXWj ... and I am not sure how to configure lazysizes like I said

Thanks for your time !

aFarkas commented 5 years ago

lazySizes is not a angular component. So it starts to work right before ngOnInit is executed.

Simply follow the normal instructions:

import lazySizes from 'lazysizes';

Object.assign(lazySizes.cfg, {
// your config goes here
});
dominicracine commented 5 years ago

That finally worked ! Thanks @aFarkas

For people trying to do a similar thing in angular 8, here's a complete version of what I did :

### Cloudinary with lazySizes in Angular 8

Reference Code :

in : your-component-name.component.css paste the same css from de CodePen ( https://codepen.io/brianluk/pen/WBNXWj )

in : your-component-name.component.html

<div class="item">
  <img id="sample" class="lazyCustom img" src="https://res.cloudinary.com/demo/image/upload/w_100,q_10,e_blur:500,f_auto/sample"
       data-sizes="auto" alt="sample">
</div>
<div class="item">
  <img id="couple" class="lazyCustom img" src="https://res.cloudinary.com/demo/image/upload/w_100,q_10,e_blur:500,f_auto/couple"
       data-sizes="auto" alt="couple">
</div>
<div class="item">
  <img id="catstronaut" class="lazyCustom img" src="https://res.cloudinary.com/demo/image/upload/w_100,q_10,e_blur:500,f_auto/catstronaut"
       data-sizes="auto" alt="catstronaut">
</div>
<div class="item">
  <img id="flamingo" class="lazyCustom img" src="https://res.cloudinary.com/demo/image/upload/w_100,q_10,e_blur:500,f_auto/flamingo"
       data-sizes="auto" alt="flamingo">
</div>
<div class="item">
  <img id="tiled_1265923066" class="lazyCustom img" src="https://res.cloudinary.com/demo/image/upload/w_100,q_10,e_blur:500,f_auto/tiled_1265923066"
       data-sizes="auto" alt="tiled_1265923066">
</div>

in : your-component-name.component.ts

import {Component, OnInit, Renderer2} from '@angular/core';

@Component({
  selector: 'app-your-component-name',
  templateUrl: './your-component-name.component.html',
  styleUrls: ['./your-component-name.component.css']
})
export class yourComponentNameComponent implements OnInit {
  images: any;

  constructor(private renderer: Renderer2) {
  }

  ngOnInit() {
    this.images = document.getElementsByClassName('lazyCustom');

    for (const image of this.images) {
      this.renderer.setAttribute(image, 'data-src', image.id);
    }
  }
}

Then, create a folder in :
src/assets/js And create a .js file the name you want. I named it custom.js src/assets/js/custom.js

Then, paste your configuration there : here's my congif :

// configure available widths to replace with the {width} placeholder
var widths = [540, 900, 1080, 1512, 1944];
var widthMappings = {};
for (i in widths) {
  widthMappings[widths[i]] = Math.floor(widths[i] * .6).toString()
}

Object.assign(lazySizes.cfg, {
  lazyClass: "lazyCustom",
  expand: 10,
  rias: {
    widths: widths,
    widthmap: widthMappings,
    prefix: "https://res.cloudinary.com/demo/image/upload/w_{width},dpr_auto,f_auto,q_auto:low/"
  }
});

Then, install lazysizes :

     npm install lazysizes --save

Then add it to your scripts in angular.json file

...
            "scripts": [
              "node_modules/lazysizes/plugins/rias/ls.rias.min.js",
              "node_modules/lazysizes/lazysizes.min.js",
              "src/assets/js/custom.js"
            ]
          },

Note** : you should restart "ng serve" every time you change the script.

Hope it was helpful

Dom

aFarkas commented 5 years ago

I really would not predefine a src attribute on img some browsers might start the download. Most can abort, but some like Safari don't.

ashok9730 commented 5 years ago

lazysizes npm only working with static img list and not working in dynamic img list like *ngFor angular

h3d0 commented 4 years ago

Angular Universal, a component uses ngFor: in the browser the components class change from lazyload to lazyloaded, however all images are still loaded on init. It looks like Universal spoils the logic somehow and loads all (even the off-screen) images anyway.

@aFarkas any comment? Is lazysizes supposed to support Angular Universal dynamic usage (e.g. ngFor)?

aFarkas commented 4 years ago

@h3d0 https://github.com/aFarkas/lazysizes#specify-dimensions

luckyboykg commented 3 years ago

From angular 2.x and more, I can make it work by this way: Import this script in your index.html file

<script
            async
            src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js"
            crossorigin="anonymous"
        ></script>

And use Img tag in your component:

<img
                            [ngClass]="['lazyload']"
                            [src]="defaultImage"
                            [attr.data-src]="yourImage"
                        />

-[ngClass]: because your class we be changed by angular -[attr.data-src]: the custom attribute in angular

jacob-flores commented 3 years ago

Tried all configurations, no one worked for me. It seems Angular is not supported since the lack of documentation. Thanks anyway

janwidmer commented 3 years ago

I was able to make it work by just adding the script to my angular.json and defining my media like this:

<img class="a-media__img lazyload"
            [attr.src]="'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='"
            [attr.data-src]="media.src"
            [attr.data-srcset]="media.srcset"
            [attr.alt]="media.alt"
            (load)="loadHandler()"
            (error)="errorHandler()"
        />