按需加载图片(图片懒加载)

时间:2021-06-25 19:26:21

前言

按需要加载图片,这是一个非常实用的功能,不仅可以提高网站的性能,还可以为你节省流量。对于用虚拟主机的朋友来说,如果你的网站是一个图片网站或者图片比较多的网站,那么图片懒加载功能真不能少。

原理

实现图片懒加载的原理也非常地简单,默认情况下不给图片 scr 属性赋值。当满足一定的条件时才把图片地址取出来赋值给 src 属性。一般地,这上为了让网站页面有更好的用户体验,我们都会预先给所有的图片都设置一张默认的图片,比如一个像素的图片或者其它任意一张图片(只要你喜欢)。

实践代码

我们还是先来看看这个 Demo:http://yunkus.com/demo/load-images-on-demand/

例子中用了一个谈入的效果(CSS 3),如果你想用更多的效果,你可以下载一下 animate.css 库,尝试不同效果展示。在这里就不作过多的讲解,至于 animate.css 库的用法你可以参考这里:

Animate.css 使用教程(一个强大的 CSS3 动画库)

CSS 样式

  
  
 
 
  1. .lazy-img-box {
  2. margin: 0 auto;
  3. width: 430px;
  4. overflow: hidden
  5. }
  6. .lazy-img-box li {
  7. list-style: none;
  8. float: left;
  9. width: 400px;
  10. height: 200px;
  11. margin-right: 12px;
  12. margin-bottom: 12px;
  13. }
  14. .lazy-img-box li img {
  15. width: 400px;
  16. height: 200px;
  17. display: block;
  18. }
  19. .animated {
  20. -webkit-animation-duration: 1s;
  21. animation-duration: 1s;
  22. -webkit-animation-fill-mode: both;
  23. animation-fill-mode: both;
  24. }
  25. @-webkit-keyframes fadeIn {
  26. from {
  27. opacity: 0;
  28. }
  29. to {
  30. opacity: 1;
  31. }
  32. }
  33. @keyframes fadeIn {
  34. from {
  35. opacity: 0;
  36. }
  37. to {
  38. opacity: 1;
  39. }
  40. }
  41. .fadeIn {
  42. -webkit-animation-name: fadeIn;
  43. animation-name: fadeIn;
  44. }

 HTML 代码

  
  
 
 
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>按需加载图片(图片懒加载)-云库网</title>
  6. <meta name="description" content="按需加载图片不仅提高网站性能,还可以为你省了不少流量!" />
  7. <meta name="keywords" content="JavaScript教程,按需加载图片,图片懒加载" />
  8. <link rel="stylesheet" href="./index.css">
  9. </head>
  10. <body>
  11. <ul class="lazy-img-box">
  12. <li><img _src="http://yunkus.com/demo/lib/images/demo-1.jpg" src="./images/loading.gif" alt=""></li>
  13. <li><img _src="http://yunkus.com/demo/lib/images/demo-2.jpg" src="./images/loading.gif" alt=""></li>
  14. <li><img _src="http://yunkus.com/demo/lib/images/demo-3.jpg" src="./images/loading.gif" alt=""></li>
  15. <li><img _src="http://yunkus.com/demo/lib/images/demo-4.jpg" src="./images/loading.gif" alt=""></li>
  16. <li><img _src="http://yunkus.com/demo/lib/images/demo-5.jpg" src="./images/loading.gif" alt=""></li>
  17. <li><img _src="http://yunkus.com/demo/lib/images/demo-6.jpg" src="./images/loading.gif" alt=""></li>
  18. <li><img _src="http://yunkus.com/demo/lib/images/demo-7.jpg" src="./images/loading.gif" alt=""></li>
  19. <li><img _src="http://yunkus.com/demo/lib/images/demo-8.jpg" src="./images/loading.gif" alt=""></li>
  20. <li><img _src="http://yunkus.com/demo/lib/images/demo-9.jpg" src="./images/loading.gif" alt=""></li>
  21. <li><img _src="http://yunkus.com/demo/lib/images/demo-1.jpg" src="./images/loading.gif" alt=""></li>
  22. <li><img _src="http://yunkus.com/demo/lib/images/demo-2.jpg" src="./images/loading.gif" alt=""></li>
  23. <li><img _src="http://yunkus.com/demo/lib/images/demo-3.jpg" src="./images/loading.gif" alt=""></li>
  24. <li><img _src="http://yunkus.com/demo/lib/images/demo-4.jpg" src="./images/loading.gif" alt=""></li>
  25. <li><img _src="http://yunkus.com/demo/lib/images/demo-5.jpg" src="./images/loading.gif" alt=""></li>
  26. <li><img _src="http://yunkus.com/demo/lib/images/demo-6.jpg" src="./images/loading.gif" alt=""></li>
  27. <li><img _src="http://yunkus.com/demo/lib/images/demo-7.jpg" src="./images/loading.gif" alt=""></li>
  28. <li><img _src="http://yunkus.com/demo/lib/images/demo-8.jpg" src="./images/loading.gif" alt=""></li>
  29. <li><img _src="http://yunkus.com/demo/lib/images/demo-9.jpg" src="./images/loading.gif" alt=""></li>
  30. </ul>
  31. <script src="./index.js"></script>
  32. </body>
  33. </html>

JavaScript 代码

  
  
 
 
  1. window.onload = function () {
  2. var lazyImg = document.getElementsByTagName("img");
  3. var lazyImgLen = lazyImg.length;
  4. var lazyImgArray = [];
  5. var winowBroswerHeight = document.documentElement.clientHeight;
  6. // 初始第一屏图片
  7. loadImg();
  8. // 滚动时执行加载图片的方法
  9. window.onscroll = loadImg;
  10. // 按需加载图片
  11. function loadImg() {
  12. for (var i = 0; i < lazyImgLen; i++) {
  13. var getTD = getTopDistance(lazyImg[i]);
  14. var getST = getScrollTop();
  15. if (!lazyImg[i].loaded && getST < getTD && getTD < (getST + winowBroswerHeight)) {
  16. lazyImg[i].src = lazyImg[i].getAttribute("_src");
  17. lazyImg[i].classList.add("animated", "fadeIn");
  18. lazyImg[i].loaded = true; // 标记为已加载
  19. }
  20. }
  21. }
  22. // 获取目录对象离 document 文档顶部的距离
  23. function getTopDistance(obj) {
  24. var TopDistance = 0;
  25. while (obj) {
  26. TopDistance += obj.offsetTop;
  27. obj = obj.offsetParent;
  28. }
  29. return TopDistance;
  30. }
  31. // 获取滚动条的滚动距离
  32. function getScrollTop() {
  33. return document.documentElement.scrollTop || document.body.scrollTop;
  34. }
  35. }

不管滚动条处于什么位置,只要你一刷新,就只会加载处于屏幕里的图片。除此之处不管是屏幕上方的图片,还是屏幕下方的图片只要还没进入屏幕区的都不会被加载。这样的处理方式理论上是比较优的,但是在实践的应用中,却不一定能发展出原有的作用。试想一下,不管你是通过地址直接访问,还是通过搜索引擎进入一个页面,一般情况下都会从页面的顶部内容开始显示,如果你有洁癖想让代码更简单,那么 loadImg() 方法就可以更改成如下代码:

  
  
 
 
  1. function loadImg() {
  2. for (var i = 0; i < lazyImgLen; i++) {
  3. var getTD = getTopDistance(lazyImg[i]);
  4. var getST = getScrollTop();
  5. if (!lazyImg[i].loaded && getTD < (getST + winowBroswerHeight)) {
  6. lazyImg[i].src = lazyImg[i].getAttribute("_src");
  7. lazyImg[i].classList.add("animated", "fadeIn");
  8. lazyImg[i].loaded = true; // 标记为已加载
  9. }
  10. }
  11. }

其实也没什么变的,只是 if 判断条件少了一个:

  
  
 
 
  1. getST < getTD

不过也有例外,比如:从列表页中点了评论时,极有可能是跳到详情页后直接跳到评论区,这种情况也很常见,此时就不需要更改代码以达到最优。

这里还有个小问题,关于滚动监听事件的,像上面那样写 window.onscroll = function(){} 一个页面只能用一个,如果有其它地主也用到这个滚动监听事件的话,那么就会只有一个起作用。在这里可以用事件绑定来解决,具体的方法可以查阅这里:常用的 JavaScript 函数封装


转自:http://yunkus.com/load-images-on-demand/