javascript瀑布流式图片懒加载实例

下面是关于 "javascript瀑布流式图片懒加载实例" 的完整攻略:

概述

本文将讲述如何使用 JavaScript 实现瀑布流式图片懒加载,以及如何实现懒加载动画效果。瀑布流是一种瀑布般的布局方式,能够有效节省页面空间,而懒加载则是一种优化网站性能的常用方法,能够有效减少页面初次加载的时间。

实现步骤

  1. 首先,需要在 HTML 文件中添加一个装载图片的容器,通常使用 div 标签。如下所示:
<div id="imageContainer">
  <!--图片显示区域-->
</div>
  1. 在 JavaScript 中获取该容器并创建需要的变量。
const imageContainer = document.getElementById('imageContainer');
let images = [];
let current = 0;
let limit = 20; // 一次加载几张图片
let imageWidth = 200; //图片的宽度
let imageHeight = 0; //图片的高度
let columnCount = 3; //瀑布流的列数
let loading = false; //加载完成标志
  1. 创建一个获取图片信息的函数,获取图片的宽度和高度信息。
function getImageInfo(image) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      // 返回图片的宽、高。
      resolve({
        width: img.width,
        height: img.height
      });
    };
    img.onerror = reject;
    img.src = image.src;
  });
}
  1. 创建一个函数,用于按瀑布流式布局展示图片。
function waterfall() {
  // 计算容器的宽度和每列的宽度
  const containerWidth = imageContainer.offsetWidth;
  const columnWidth = parseInt(containerWidth / columnCount);
  //高度数组,记录每列的高度
  const heightArr = new Array(columnCount).fill(0);

  for (let i = current; i < current + limit; i++) {
    //判断是否已经全部加载完毕
    if (i >= images.length) {
      loading = false;
      return;
    }

    // 创建图片所在的容器
    const imageItem = document.createElement('div');
    imageItem.className = 'image-item';
    imageItem.style.width = imageWidth + 'px';

    //创建图片标签
    const image = document.createElement('img');
    image.src = images[i].src;
    image.dataset.index = i;

    //计算下载完成后的图片的高度
    getImageInfo(image).then((result) => {
      imageHeight = parseInt(imageWidth * result.height / result.width);

      //根据高度和高度数组,计算图片位置
      const idx = getMinHeightIndex(heightArr);
      const left = idx * columnWidth;
      const top = heightArr[idx];

      //设置图片样式和属性
      image.style.width = imageWidth + 'px';
      image.style.height = imageHeight + 'px';
      image.style.left = left + 'px';
      image.style.top = top + 'px';
      //记录该列的高度
      heightArr[idx] += imageHeight;

      //绑定图片点击事件
      image.addEventListener('click', function () {
        console.log('你点击了第' + this.dataset.index + '张图片。');
      });

      //把该图片添加到容器中
      imageItem.append(image);
      imageContainer.append(imageItem);
    });
  }

  // 根据总高度调整容器高度
  const containerHeight = Math.max.apply(null, heightArr);
  imageContainer.style.height = containerHeight + 'px';

  //增加计数器
  current += limit;
}
  1. 创建一个函数,用于获取当前高度最小的列序号。
function getMinHeightIndex(arr) {
  let index = 0;
  let minHeight = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < minHeight) {
      minHeight = arr[i];
      index = i;
    }
  }
  return index;
}
  1. 创建一个触发懒加载的函数。
function checkScroll() {
  const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
  const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;

  if (scrollTop + clientHeight >= scrollHeight - 50 && !loading) {
    loading = true;
    //进行瀑布流式布局展示图片
    waterfall();
  }
}
  1. 监听滚动事件,当滚动到页面底部时,进行懒加载。
window.addEventListener('scroll', function () {
  checkScroll();
});
  1. 最后,在 CSS 中添加样式。
#imageContainer {
  position: relative;
}

.image-item {
  position: absolute;
  transition: opacity 0.5s;
}

示例1

假设我们有一组图片 image1.jpg ~ image30.jpg,这些图片的宽度和高度不一,我们希望按照瀑布流式布局展示图片,同时采用懒加载方式加载图片,还想通过添加动画效果来使图片加载更加流畅。

<!--html-->
<div id="imageContainer"></div>

<!--css-->
<style>
#imageContainer {
  position: relative;
}

.image-item {
  position: absolute;
  transition: opacity 0.5s;
}
</style>

<!--javascript-->
<script>
const imageContainer = document.getElementById('imageContainer');
let images = [];
let current = 0;
let limit = 20;
let imageWidth = 200;
let imageHeight = 0;
let columnCount = 3;
let loading = false;

//获取图片信息函数
function getImageInfo(image) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      resolve({
        width: img.width,
        height: img.height
      });
    };
    img.onerror = reject;
    img.src = image.src;
  });
}

//瀑布流式布局函数
function waterfall() {
  const containerWidth = imageContainer.offsetWidth;
  const columnWidth = parseInt(containerWidth / columnCount);
  const heightArr = new Array(columnCount).fill(0);

  for (let i = current; i < current + limit; i++) {
    if (i >= images.length) {
      loading = false;
      return;
    }

    const imageItem = document.createElement('div');
    imageItem.className = 'image-item';
    imageItem.style.width = imageWidth + 'px';

    const image = document.createElement('img');
    image.src = images[i].src;
    image.dataset.index = i;
    getImageInfo(image).then((result) => {
      imageHeight = parseInt(imageWidth * result.height / result.width);

      const idx = getMinHeightIndex(heightArr);
      const left = idx * columnWidth;
      const top = heightArr[idx];

      image.style.width = imageWidth + 'px';
      image.style.height = imageHeight + 'px';
      image.style.left = left + 'px';
      image.style.top = top + 'px';

      heightArr[idx] += imageHeight;

      image.addEventListener('click', function () {
        console.log('你点击了第' + this.dataset.index + '张图片。');
      });

      imageItem.append(image);
      imageContainer.append(imageItem);
      imageItem.style.opacity = 1;
    });
  }

  const containerHeight = Math.max.apply(null, heightArr);
  imageContainer.style.height = containerHeight + 'px';

  current += limit;
}

//获取当前高度最小的列数
function getMinHeightIndex(arr) {
  let index = 0;
  let minHeight = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < minHeight) {
      minHeight = arr[i];
      index = i;
    }
  }
  return index;
}

//触发懒加载
function checkScroll() {
  const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
  const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;

  if (scrollTop + clientHeight >= scrollHeight - 50 && !loading) {
    loading = true;
    waterfall();
  }
}

//监听页面滚动事件
window.addEventListener('scroll', function () {
  checkScroll();
});

//加载图片
for (let i = 1; i <= 30; i++) {
  images.push({
    src: 'image' + i + '.jpg'
  });
}
</script>

示例2

接下来,我们添加一个懒加载动画效果,让图片加载更显流畅。

<!--html-->
<div id="imageContainer"></div>

<!--css-->
<style>
#imageContainer {
  position: relative;
}

.image-item {
  position: absolute;
  transition: opacity 0.5s;
}

.loader {
  width: 30px;
  height: 30px;
  border: 5px solid #f3f3f3;
  border-top-color: #3498db;
  border-radius: 50%;
  animation: spin 2s linear infinite;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -15px;
  margin-top: -15px;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>

<!--javascript-->
<script>
const imageContainer = document.getElementById('imageContainer');
let images = [];
let current = 0;
let limit = 20;
let imageWidth = 200;
let imageHeight = 0;
let columnCount = 3;
let loading = false;

//获取图片信息函数
function getImageInfo(image) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      resolve({
        width: img.width,
        height: img.height
      });
    };
    img.onerror = reject;
    img.src = image.src;
  });
}

//瀑布流式布局函数
function waterfall() {
  const containerWidth = imageContainer.offsetWidth;
  const columnWidth = parseInt(containerWidth / columnCount);
  const heightArr = new Array(columnCount).fill(0);

  for (let i = current; i < current + limit; i++) {
    if (i >= images.length) {
      loading = false;
      return;
    }

    const imageItem = document.createElement('div');
    imageItem.className = 'image-item';
    imageItem.style.width = imageWidth + 'px';

    const image = document.createElement('img');
    image.src = images[i].src;
    image.dataset.index = i;

    //添加加载动画
    const loader = document.createElement('div');
    loader.className = 'loader';
    imageItem.append(loader);

    getImageInfo(image).then((result) => {
      imageHeight = parseInt(imageWidth * result.height / result.width);

      const idx = getMinHeightIndex(heightArr);
      const left = idx * columnWidth;
      const top = heightArr[idx];

      image.style.width = imageWidth + 'px';
      image.style.height = imageHeight + 'px';
      image.style.left = left + 'px';
      image.style.top = top + 'px';

      heightArr[idx] += imageHeight;

      image.addEventListener('click', function () {
        console.log('你点击了第' + this.dataset.index + '张图片。');
      });

      imageItem.append(image);
      imageContainer.append(imageItem);
      imageItem.style.opacity = 1;
      //移除加载动画
      imageItem.removeChild(loader);
    });
  }

  const containerHeight = Math.max.apply(null, heightArr);
  imageContainer.style.height = containerHeight + 'px';

  current += limit;
}

//获取当前高度最小的列数
function getMinHeightIndex(arr) {
  let index = 0;
  let minHeight = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < minHeight) {
      minHeight = arr[i];
      index = i;
    }
  }
  return index;
}

//触发懒加载
function checkScroll() {
  const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
  const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;

  if (scrollTop + clientHeight >= scrollHeight - 50 && !loading) {
    loading = true;
    waterfall();
  }
}

//监听页面滚动事件
window.addEventListener('scroll', function () {
  checkScroll();
});

//加载图片
for (let i = 1; i <= 30; i++) {
  images.push({
    src: 'image' + i + '.jpg'
  });
}
</script>

这就是实现 "javascript瀑布流式图片懒加载实例" 的完整攻略。相信在这份攻略的指引下,您可以轻松地实现瀑布流式图片懒加载的效果,并增加一些流畅的动画效果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:javascript瀑布流式图片懒加载实例 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • vs2010打包安装包带数据库

    VS2010打包安装包带数据库 在软件开发过程中,经常需要将开发完成的程序打包成安装包进行发布。为了方便用户的安装,可以将程序的依赖项也打包进去,比如数据库。本文将介绍如何使用VS2010打包安装包并将数据库一起打包。 准备工作 在开始之前,需要安装VS2010和SQL Server 2008 R2(假设你的程序是基于该版本的数据库开发的)。同时,需要确保你…

    其他 2023年3月28日
    00
  • 新手建站入门教程④:如何绑定子目录

    首先,在使用子目录时需要了解什么是子目录。子目录是站点目录下的一级目录,通过子目录可以将站点内容进行分类、归档,同时也可以方便地管理网站内容。 其次,本教程将讲解如何将新的子目录绑定到现有站点上。需要注意的是,在添加子目录之后,需要对子目录的文件进行调整,以确保子目录中的文件能够正确地呈现。 下面,我们分别讲解添加子目录的详细步骤: 1. 添加子目录 首先,…

    other 2023年6月27日
    00
  • SpringBoot读取配置文件常用方法解析

    SpringBoot读取配置文件常用方法解析 在SpringBoot应用中,读取配置文件是十分常见的操作,SpringBoot为读取配置文件提供了多种方式,下面对这些方法进行详细解析。 1. 使用@Value注解 @Value注解是Spring框架中常用的用于获取配置文件中属性值的注解,也可以用于将自定义配置属性值注入到Spring管理的Bean中。使用方法…

    other 2023年6月25日
    00
  • react-router-dom 嵌套路由的实现

    React Router Dom 嵌套路由的实现攻略 React Router Dom 是一个用于在 React 应用中实现路由功能的库。它提供了一种简单而强大的方式来管理应用程序的不同页面之间的导航。 嵌套路由是指在一个页面中嵌套另一个页面的路由。这种技术可以帮助我们构建复杂的应用程序,其中每个页面可以有自己的子页面。 下面是实现嵌套路由的完整攻略: 步骤…

    other 2023年7月28日
    00
  • 常用的9个网络命令 非常实用

    常用的9个网络命令 非常实用 作为网络管理和维护的人员,掌握一些常用的网络命令和工具非常重要。本文将介绍9个常用的网络命令,让你能更好的了解网络的运作和维护。 1. ping ping命令用于测试网络连接并检测网络延迟。其语法为: ping [options] <host> 其中,options是可选的参数,host是需要测试的主机名或IP地址。…

    other 2023年6月26日
    00
  • iOS消息推送原理及具体实现代码

    iOS消息推送原理及具体实现代码 1. 原理概述 iOS消息推送(Push Notification)是指通过苹果提供的APNS(Apple Push Notification Service)服务,向用户设备发送消息的一种技术。其主要原理是:应用程序通过向APNS发送推送请求,APNS将推送请求发送到用户设备上的iOS系统,然后iOS系统将推送消息发送到应…

    other 2023年6月26日
    00
  • 详解React项目的服务端渲染改造(koa2+webpack3.11)

    详解React项目的服务端渲染改造(koa2+webpack3.11) 1. 概述 本文将介绍如何将一个React项目改造成服务端渲染的形式,并使用Koa2和webpack3.11完成。 服务端渲染的好处是能够提高网站的SEO和首屏渲染速度,并且能够更好地应对一些搜索引擎不友好的单页面应用(SPA)。通过本文,你将掌握如何在一个React项目中加入服务端渲染…

    other 2023年6月27日
    00
  • ASP.NET Core MVC 过滤器的使用方法介绍

    ASP.NET Core MVC 过滤器的使用方法介绍 ASP.NET Core MVC 过滤器是一种用于在请求处理过程中执行预定义逻辑的组件。它们可以用于处理请求前后的操作,例如身份验证、授权、日志记录等。本攻略将详细介绍 ASP.NET Core MVC 过滤器的使用方法,并提供两个示例说明。 1. 过滤器的类型 ASP.NET Core MVC 提供了…

    other 2023年8月20日
    00
合作推广
合作推广
分享本页
返回顶部