LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

使用 HTML + JavaScript 实现图片懒加载功能(附完整代码)

admin
2025年12月23日 9:20 本文热度 1012
现代Web开发中,性能优化是提升用户体验的重要因素之一。当页面包含大量图片时,如果一次性加载所有图片,不仅会消耗大量带宽,还会严重影响页面加载速度。图片懒加载(Lazy Loading)技术可以有效解决这个问题,它只在用户滚动到图片可见区域时才加载图片,从而显著提升页面加载速度和用户体验。本文将详细介绍如何使用 HTML、CSS 和 JavaScript 实现一个高效的图片懒加载解决方案。

效果演示

本系统通过一个图片网格布局展示懒加载功能的效果。页面初始加载时,只显示在视口内的图片,其他图片会显示加载占位符。当用户向下滚动页面,图片即将进入视口时,才会开始加载实际图片并显示加载动画。这种技术可以显著减少初始页面加载时间,节省带宽,并提升整体性能。

页面结构

页面采用网格布局展示图片内容,包含图片容器区域、加载占位符和图片信息区域。

图片网格容器

图片网格容器使用CSS Grid布局,将图片以2列形式排列,每张图片都有独立的包装容器和信息区域。
<div class="container">  <h1>图片懒加载演示</h1>  <div class="image-grid" id="imageContainer"></div></div>

图片项结构

每个图片项包含图片包装器和信息区域,其中图片包装器内包含懒加载图片元素和加载占位符。
<div class="image-item">  <div class="image-wrapper">    <img class="lazy-image" data-src="https://picsum.photos/800/400?random=13" alt="示例图片 13">    <div class="loading-placeholder">      <div class="loading-spinner"></div>    </div>  </div>  <div class="image-info">    <h3 class="image-title">风景图片 13</h3>    <p class="image-desc">这是第 13 张示例图片,展示了美丽的风景。图片会在滚动到视口时才开始加载,节省带宽和提升页面加载速度。</p>  </div></div>

核心功能实现

LazyLoader 类实现了图片懒加载的核心逻辑,主要包含以下功能:

  • 初始化Intersection Observer - 监听图片元素是否进入视口

  • 图片加载逻辑 - 当图片进入视口时,从 data-src 属性获取真实图片URL并加载

  • 加载状态管理 - 显示加载动画,处理加载成功/失败的情况

Intersection Observer配置

Intersection Observer 是实现懒加载的关键技术,它提供了一种异步检测目标元素与祖先元素或视口相交情况的方法,相比传统的滚动事件监听更加高效。
init() {  const config = {    rootMargin'100px 0px',    threshold0.01  };
  this.imageObserver = new IntersectionObserver((entries, observer) => {    entries.forEach(entry => {      if (entry.isIntersecting) {        this.loadImage(entry.target);        observer.unobserve(entry.target);      }    });  }, config);}

图片加载逻辑

当图片元素进入视口时,loadImage 方法会创建一个临时的 Image 对象进行预加载,这样可以确保图片完全加载后再显示到页面上,提供更好的用户体验。同时,该方法还处理了加载失败的情况,显示默认的错误图片。
loadImage(img) {  const dataSrc = img.getAttribute('data-src');  if (!dataSrc) return;  const placeholder = img.parentElement.querySelector('.loading-placeholder');  // 创建新图片对象预加载  const tempImg = new Image();  tempImg.onload = () => {    // 预加载完成后应用到实际图片    img.src = dataSrc;    img.classList.add('loaded');    if (placeholder) {      placeholder.style.display = 'none';    }  };  // 加载失败处理  tempImg.onerror = () => {    img.src = 'data:image/svg+xml;utf8,<svg width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="400" height="400" fill="%23F5F5F5"/><text x="200" y="200" font-family="Arial" font-size="16" fill="%23999" text-anchor="middle">图片加载失败</text></svg>';    img.classList.add('loaded');    if (placeholder) {      placeholder.style.display = 'none';    }  };  // 开始加载  tempImg.src = dataSrc;}

完整代码

git地址:https://gitee.com/ironpro/hjdemo/blob/master/image-lazy/index.html
<!DOCTYPE html><html lang="zh-CN"><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>图片懒加载</title>  <style>    * {        margin0;        padding0;        box-sizing: border-box;    }    body {        background-color#f8f9fa;        padding20px;        min-height100vh;        color#333;    }    .container {        max-width1020px;        margin0 auto;    }    h1 {        text-align: center;        margin-bottom30px;        color#2c3e50;        font-size28px;        font-weight500;    }    .image-grid {        display: grid;        grid-template-columnsrepeat(21fr);        gap20px;    }    .image-item {        background#fff;        overflow: hidden;        box-shadow0 2px 8px rgba(0000.1);        transition: transform 0.2s ease, box-shadow 0.2s ease;        margin-bottom0;    }    .image-item:hover {        box-shadow0 4px 16px rgba(0000.15);    }    .image-wrapper {        position: relative;        width100%;        height300px;        background-color#f1f3f4;        overflow: hidden;    }    .lazy-image {        width100%;        height100%;        object-fit: cover;        opacity0;        transition: opacity 0.3s ease;    }    .lazy-image.loaded {        opacity1;    }    .loading-placeholder {        position: absolute;        top50%;        left50%;        transformtranslate(-50%, -50%);        width40px;        height40px;    }    .loading-spinner {        width100%;        height100%;        border2px solid #e0e0e0;        border-top2px solid #3498db;        border-radius50%;        animation: spin 1s linear infinite;    }    @keyframes spin {        0% { transformrotate(0deg); }        100% { transformrotate(360deg); }    }    .image-info {        padding20px;    }    .image-title {        font-size18px;        margin-bottom8px;        font-weight500;        color#2c3e50;    }    .image-desc {        font-size14px;        color#666;        line-height1.5;    }</style></head><body><div class="container">  <h1>图片懒加载演示</h1>  <div class="image-grid" id="imageContainer"></div></div><script>  class LazyLoader {    constructor() {      this.imageObserver = null;      this.init();    }    init() {      const config = {        rootMargin'100px 0px',        threshold0.01      };
      this.imageObserver = new IntersectionObserver((entries, observer) => {        entries.forEach(entry => {          if (entry.isIntersecting) {            this.loadImage(entry.target);            observer.unobserve(entry.target);          }        });      }, config);    }
    loadImage(img) {      const dataSrc = img.getAttribute('data-src');      if (!dataSrc) return;      const placeholder = img.parentElement.querySelector('.loading-placeholder');      // 创建新图片对象预加载      const tempImg = new Image();      tempImg.onload = () => {        // 预加载完成后应用到实际图片        img.src = dataSrc;        img.classList.add('loaded');        if (placeholder) {          placeholder.style.display = 'none';        }      };      // 加载失败处理      tempImg.onerror = () => {        img.src = 'data:image/svg+xml;utf8,<svg width="100%" height="300" viewBox="0 0 400 300" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="400" height="300" fill="%23F5F5F5"/><text x="200" y="150" font-family="Arial" font-size="16" fill="%23999" text-anchor="middle">图片加载失败</text></svg>';        img.classList.add('loaded');        if (placeholder) {          placeholder.style.display = 'none';        }      };      // 开始加载      tempImg.src = dataSrc;    }
    observe(img) {      this.imageObserver.observe(img);    }  }  // 生成图片数据  function generateImageData(count) {    const images = [];    for (let i = 1; i <= count; i++) {      images.push({        title`风景图片 ${i}`,        description`这是第 ${i} 张示例图片,展示了美丽的风景。图片会在滚动到视口时才开始加载,节省带宽和提升页面加载速度。`,        src`https://picsum.photos/800/400?random=${i}`,        alt`示例图片 ${i}`      });    }    return images;  }  // 创建图片元素  function createImageElement(imageData) {    const div = document.createElement('div');    div.className = 'image-item';    div.innerHTML = `<div class="image-wrapper">                    <img class="lazy-image" data-src="${imageData.src}" alt="${imageData.alt}">                    <div class="loading-placeholder">                        <div class="loading-spinner"></div>                    </div>                </div>                <div class="image-info">                    <h3 class="image-title">${imageData.title}</h3>                    <p class="image-desc">${imageData.description}</p>                </div>`;    return div;  }  document.addEventListener('DOMContentLoaded'function() {    const container = document.getElementById('imageContainer');    const lazyLoader = new LazyLoader();    // 生成30张图片    const images = generateImageData(30);    // 添加到页面并设置懒加载    images.forEach(imageData => {      const element = createImageElement(imageData);      container.appendChild(element);      // 获取图片元素并设置观察      const img = element.querySelector('.lazy-image');      lazyLoader.observe(img);    });  });</script></body></html>


阅读原文:原文链接


该文章在 2025/12/23 10:17:18 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved