沃梦达 / IT编程 / 前端开发 / 正文

javascript实现瀑布流动态加载图片原理

JavaScript实现瀑布流动态加载图片主要涉及到以下几个方面的内容:

JavaScript实现瀑布流动态加载图片主要涉及到以下几个方面的内容:

  1. 获取图片数据
  2. 动态创建图片元素
  3. 计算图片位置
  4. 监听滚动事件
  5. 懒加载图片

下面我们一一讲解。

获取图片数据

瀑布流需要加载大量的图片,首先需要获取图片的数据。需要注意的是,为了实现动态加载,我们要考虑异步加载。

示例代码:

function getImagesData(callback) {
  fetch('http://example.com/images') // 发送请求获取图片数据
    .then(response => response.json()) // 将返回结果解析为JSON格式
    .then(data => callback(data)) // 将解析后的数据通过回调函数传回
    .catch(error => console.error(error)); // 处理错误
}

通过上面的代码,我们可以从服务器获取到图片的数据并进行处理。但是如果图片数据很多,这样一次性获取所有图片的数据会占用很多网络带宽和资源,从而影响页面加载速度。因此,我们需要动态地去生成图片元素,而不是一次性地获取所有图片的数据。

动态创建图片元素

我们可以通过document.createElement方法动态地创建图片元素,并将图片数据中的图片地址赋值给img元素的src属性。

示例代码:

function createImageElement(data) {
  const img = document.createElement('img');
  img.src = data.url;
  // 此处可以设置图片的其他属性
  return img;
}

上述代码首先创建了一个img元素,并将图片URL赋值给imgsrc属性,然后可以根据需要为该元素设置其他属性。

计算图片位置

计算图片的位置是瀑布流实现的核心,下面我们来解释一下具体实现思路。

首先,我们需要设计一个对象,来保存各列的高度,方便我们对之后的图片进行定位。

示例代码:

const columns = [
  { height: 0, elem: document.querySelector('.col1') },
  { height: 0, elem: document.querySelector('.col2') },
  // ...
];

对象数组columns中,每个对象分别保存了列的高度以及对应的DOM元素。

然后在每次添加图片的时候,我们就可以通过计算高度最小的那一列的高度,来定位新加入的图片。

示例代码:

function getPosition() {
  let minHeight = columns[0].height;
  let minColumn = 0;
  for (let i = 1; i < columns.length; i++) {
    if (columns[i].height < minHeight) {
      minHeight = columns[i].height;
      minColumn = i;
    }
  }
  return minColumn;
}

function setLocation(img) {
  const minIndex = getPosition();
  const { height } = columns[minIndex];
  const width = img.offsetWidth;
  const left = minIndex * (width + 10);
  const top = height + 10;
  img.style.cssText = `left:${left}px;top:${top}px;`;
  columns[minIndex].height += img.offsetHeight + 10;
}

getPosition函数中,我们计算出高度最小的列的索引。在setLocation函数中,我们通过该索引计算出图片的位置信息,并通过cssText设置img的样式属性。

监听滚动事件

在页面加载或者滚动时,需要检查是否需要加载新的图片。这里我们考虑在页面滚动到底部或者接近底部时,加载新的图片。

示例代码:

let isLoading = false; // 判断是否正在加载的标识

function lazyLoad() {
  if (isLoading) return; // 当前正在进行加载则退出
  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 + 300 >= scrollHeight) {
    isLoading = true; // 标记为正在加载
    getImagesData(data => {
      data.forEach(item => {
        const img = createImageElement(item);
        setLocation(img);
        document.body.appendChild(img);
      });
      isLoading = false; // 标记为加载完成
    });
  }
}

window.addEventListener('scroll', lazyLoad);

lazyLoad函数中,首先获取滚动条滚动的高度、可视区域的高度以及文档的高度,然后计算是否已经滚动到页面底部或接近底部,在此情况下,我们就可以执行图片加载操作。

值得注意的是,在getImagesData函数执行之前,需要将isLoading标识设置为true,表示正在加载。在回调函数中,当所有图片加载完成之后,需要将该标识重置为false

懒加载图片

为了提高页面加载速度,我们还需要使用懒加载技术。图片的懒加载可以使用Intersection Observer实现。

示例代码:

const observer = new IntersectionObserver(entries => {
  // 如果进入视窗的元素是图片,则将其加载
  entries.forEach(entry => {
    if (entry.isIntersecting && entry.target.tagName.toLowerCase() === 'img') {
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img); // 停止观察已经加载的图片
    }
  });
});

function lazyLoadByObserver() {
  const imgs = document.querySelectorAll('img[data-src]');
  imgs.forEach(img => observer.observe(img));
}

上述代码首先创建了一个IntersectionObserver观察器,并通过observe方法观察所有具有data-src属性的图片。当某个图片进入视窗时,观察器就会调用回调函数,这时我们就可以将img元素的data-src属性赋值给src属性,从而加载图片。

最后,我们需要在页面加载完成之后进行一次图片的懒加载:

window.addEventListener('load', lazyLoadByObserver);

至此,我们就完成了JavaScript实现瀑布流动态加载图片的完整攻略。

本文标题为:javascript实现瀑布流动态加载图片原理