当前位置:网站首页>图片懒加载(纯手写)

图片懒加载(纯手写)

2022-08-10 23:36:00 朝阳39

什么是图片懒加载?

默认情况下不加载图片,直到滚动页面,图片进入浏览器窗口的可视区域,才加载图片!

图片懒加载效果预览

在这里插入图片描述

图片懒加载实现原理

图片默认的src属性为空,图片地址存放在data-src属性中,当图片进入可视区域,从data-src属性中取得图片地址,赋值给src属性完成图片的加载

图片懒加载的实现方案

  1. 全局监听浏览器滚动事件
  2. 滚动事件中判断是否有图片进入可视区域
  3. 若图片进入可视区域,则加载图片
  4. 加载图片的过程为:从data-src属性中取得图片地址,赋值给src属性

图片懒加载的完整范例代码

目录结构
在这里插入图片描述

index.html

<!DOCTYPE html>
<html>
  <head>
    <title></title>
  </head>
  <body>
    <div style="height: 1000px">
      <img src="./images/1.jpg" />
    </div>
    <div>
      <img class="lazy-element" data-src="./images/2.jpg" />
    </div>
    <div>
      <img class="lazy-element" data-src="./images/3.jpg" />
    </div>
    <div>
      <img class="lazy-element" data-src="./images/4.jpg" />
    </div>

    <script type="text/javascript" src="./lazy.js"></script>
  </body>
</html>

lazy.js

/* 图片懒加载的原理: 图片默认的src属性为空,图片地址存放在data-src属性中 >> 当图片进入可视区域 - 从data-src属性中取得图片地址,赋值给src属性完成图片的加载 图片懒加载的实现方案: 1. 全局监听浏览器滚动事件 2. 滚动事件中判断是否有图片进入可视区域 3. 若图片进入可视区域,则加载图片 4. 加载图片的过程为:从data-src属性中取得图片地址,赋值给src属性 */

// 设定懒加载元素的样式名为 lazy-element
let lazyElementClassName = "lazy-element";

// 设定存储图片地址的属性为 data-src
let srcAttrName = "data-src";

// 定义变量--存储浏览器窗口的高度;
let _viewportHeight;
// 定义变量--存储浏览器窗口与页面顶部的距离;
let _pageYOffset;

// 更新浏览器窗口的高度
function setViewportHeight() {
    
  _viewportHeight =
    window.innerHeight ||
    document.documentElement.clientHeight ||
    document.body.clientHeight;
}

// 更新浏览器窗口与页面顶部的距离
function setPageYOffset() {
    
  _pageYOffset =
    window.pageYOffset ||
    window.scrollY ||
    document.documentElement.scrollTop ||
    document.body.scrollTop;
}

// 通过 getElementsByClassName 获取所有懒加载元素(数据类型为类似数组的HTMLCollection)
// 使用Array.prototype.slice.call方法将HTMLCollection转化为数组
let elements = Array.prototype.slice.call(
  document.getElementsByClassName(lazyElementClassName)
);

// 设定一个标记 —— 页面是否滚动(默认未滚动)
let initialized = false;

// 初始化浏览器窗口的高度
setViewportHeight();

// 全局监听浏览器滚动事件
window.onscroll = function () {
    
  // 浏览器滚动时,触发懒加载图片的检测
  scrollEventHandler();
  // 页面滚动时,更新浏览器窗口与页面顶部的距离
  setPageYOffset();
};

// 全局监听浏览器窗口大小改变事件
window.onresize = function () {
    
  // 浏览器窗口大小改变时,更新浏览器窗口的高度
  setViewportHeight();
};

function scrollEventHandler() {
    
  // 页面滚动时
  if (!initialized) {
    
    requestAnimationFrame(function update() {
    
      // 判断是否加载图片
      checkAvailable();
      // requestAnimationFrame 的回调函数只会被调用一次,如果希望每帧都执行,则每帧都需要调用
      requestAnimationFrame(update);
    });
  }
  // 滚动过后,标记为页面已滚动
  initialized = true;
}

// 判断是否加载图片
function checkAvailable() {
    
  for (let i = 0; i < elements.length; i++) {
    
    let el = elements[i];

    // 一旦检测发现进入可视区域
    if (checkElementIsInViewport(el)) {
    
      // 则加载图片
      loadElement(el);

      // 并将该元素踢出队列
      elements.splice(i--, 1);
    }
  }
}

// 判断元素是否进入可视区域
function checkElementIsInViewport(elem) {
    
  if (elem.getBoundingClientRect) {
    
    // getBoundingClientRect方法用于获取元素相对于视口左上方的位移;
    let elemPos = elem.getBoundingClientRect();

    // 元素与视口顶部的距离小于或等于视口高度时,元素进入可视区域
    if (elemPos.top && elemPos.top > 0 && elemPos.top <= _viewportHeight) {
    
      return true;
    }
    return false;
  } else {
    
    // 兼容不支持getBoundingClientRect的浏览器
    let offsetTop = getElemOffsetTop(elem);

    // 元素与页面顶部的距离小于或等于视口高度+视口顶部与页面顶部的距离时,元素进入可视区域
    if (
      offsetTop > _pageYOffset &&
      offsetTop < _pageYOffset + _viewportHeight
    ) {
    
      return true;
    }
    return false;
  }
}

// 获取元素与页面顶部的距离
function getElemOffsetTop(el) {
    
  let top = el.offsetTop;
  let parent = el.offsetParent;
  while (parent) {
    
    top += parent.offsetTop || 0;
    parent = parent.offsetParent;
  }
  return top;
}

// 加载图片: 从data-src属性中取得图片地址,赋值给src属性
function loadElement(elem) {
    
  let srcURL = elem.getAttribute(srcAttrName);
  elem.src = srcURL;
}
原网站

版权声明
本文为[朝阳39]所创,转载请带上原文链接,感谢
https://sunshinehu.blog.csdn.net/article/details/126263221