延迟加载图片元素

Lazyloading picture elements

我正在寻找有关如何最好地延迟加载图片元素的建议。我可能喜欢使用一个小的 jQuery 辅助函数来确定图片是否为 "on screen"。但是 srcset 的延迟获取,我现在不确定该怎么做。那么,有什么想法吗?

这是我正在使用的图片元素的示例。谢谢!

<picture alt="Random Celebrities" data-src="http://www.example.com/r/c_1,h_478,w_478/2015/03/19/random-celebrities-08-560x560.jpg">
    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source class='picture-source-1260' srcset='http://www.example.com/r/c_1,h_239,w_239/2015/03/19/random-celebrities-08-560x560.jpg, http://www.example.com/r/c_1,h_478,w_478/2015/03/19/random-celebrities-08-560x560.jpg 2x' media='(min-width: 1260px)'>
    <source class='picture-source-960' srcset='http://www.example.com/r/c_1,h_180,w_180/2015/03/19/random-celebrities-08-560x560.jpg, http://www.example.com/r/c_1,h_360,w_360/2015/03/19/random-celebrities-08-560x560.jpg 2x' media='(min-width: 960px)'>
    <source class='picture-source-760' srcset='http://www.example.com/r/c_1,h_150,w_150/2015/03/19/random-celebrities-08-560x560.jpg, http://www.example.com/r/c_1,h_300,w_300/2015/03/19/random-celebrities-08-560x560.jpg 2x' media='(min-width: 760px)'>
    <source class='picture-source-450' srcset='http://www.example.com/r/c_1,h_210,w_210/2015/03/19/random-celebrities-08-560x560.jpg, http://www.example.com/r/c_1,h_420,w_420/2015/03/19/random-celebrities-08-560x560.jpg 2x' media='(min-width: 450px)'>
    <source class='picture-source-320' srcset='http://www.example.com/r/c_1,h_160,w_160/2015/03/19/random-celebrities-08-560x560.jpg, http://www.example.com/r/c_1,h_320,w_320/2015/03/19/random-celebrities-08-560x560.jpg 2x'>
    <!--[if IE 9]></video><![endif]-->
    <noscript>
        <img class="picture-img-noscript" src="http://www.example.com/r/c_1,h_160,w_160/2015/03/19/random-celebrities-08-560x560.jpg" alt="Random Celebrities" />
    </noscript>
    <img class="picture-img" srcset="http://www.example.com/r/c_1,h_160,w_160/2015/03/19/random-celebrities-08-560x560.jpg" alt="Random Celebrities" />
</picture>

使用lazysizes,它是一个用于正常和响应式图像(包括图片元素)的高性能延迟加载器。

你真的不需要插件,只要在你的图片标签上放一个class,去掉里面的"img"标签,然后把src放在srcset里面:

 <picture class="lazy">
   <source srcset='/images/image.jpg'/>
 </picture>

然后在 javascript 加载 dom 后:

获取所有“.lazy”节点:

const lazyImages = document.querySelectorAll('.lazy');

像这样调用一个函数:

 function lazyLoadImages() {
   lazyImages.forEach((val,i) => {

     let src = val.querySelector('source').getAttribute('srcset');
     let image = new Image();
     image.src = src;
     val.append(image);


   })
 }

我在这里创建了一个带有解决方案的笔:

codepen

在 Chrome & Firefox、Safari 和 IE11 中测试(后者的后备)

<!-- Load images above the fold normally -->
<picture>
  <source srcset="img/city-m.jpg" media="(max-width: 960px)">
  <source srcset="img/city-l.jpg" media="(min-width: 961px)">
  <img class="fade-in" src="img/city-l.jpg" alt="city"/>
</picture>

<picture>
  <source srcset="img/forest-m.jpg" media="(max-width: 960px)">
  <source srcset="img/forest-l.jpg" media="(min-width: 961px)">
  <img class="fade-in" src="img/forest-l.jpg" alt="forest"/>
</picture>

<!-- Lazy load images below the fold -->
<picture class="lazy">
  <source data-srcset="img/river-m.jpg" media="(max-width: 960px)">
  <source data-srcset="img/river-l.jpg" media="(min-width: 961px)">
  <img data-srcset="img/river-l.jpg" alt="river"/>
</picture>

<picture class="lazy">
  <source data-srcset="img/desert-m.jpg" media="(max-width: 960px)">
  <source data-srcset="img/desert-l.jpg" media="(min-width: 961px)">
  <img data-srcset="img/desert-l.jpg" alt="desert"/>
</picture>

和 JS:

document.addEventListener("DOMContentLoaded", function(event) {
   var lazyImages =[].slice.call(
    document.querySelectorAll(".lazy > source")
   )

   if ("IntersectionObserver" in window) {
      let lazyImageObserver = 
       new IntersectionObserver(function(entries, observer) {
          entries.forEach(function(entry) {
           if (entry.isIntersecting) {      
              let lazyImage = entry.target;
              lazyImage.srcset = lazyImage.dataset.srcset;
              lazyImage.nextElementSibling.srcset = lazyImage.dataset.srcset;
              lazyImage.nextElementSibling.classList.add('fade-in');
              lazyImage.parentElement.classList.remove("lazy");
             lazyImageObserver.unobserve(lazyImage);
            }
         });
        });

      lazyImages.forEach(function(lazyImage) {
       lazyImageObserver.observe(lazyImage);
      });
   } else {
     // Not supported, load all images immediately
    lazyImages.forEach(function(image){
        image.nextElementSibling.src = image.nextElementSibling.dataset.srcset;
      });
    }
  });