原生JS实现美图瀑布流布局赏析

标题:原生JS实现美图瀑布流布局赏析

什么是瀑布流布局?

瀑布流布局是一种常见的网页布局方式,参考了瀑布流的设计,将页面上的元素按照一定规则排列,使得即便是不同尺寸、不同比例的元素也能够合理地被摆放。常见的网站如Pinterest、Instagram等都采用了瀑布流布局。

实现原理

实现瀑布流布局最核心的思路就是要能掌握两个问题:

  1. 如何确定每个元素的左右边距?

  2. 如何确定每个元素的上下边距?

对于第一个问题,我们一般采用的是“列宽一致,间距自适应”的方式。即我们先给出每一列的宽度,然后根据页面的实际宽度自动计算每一列之间的间距,进而实现元素的左右边距的自适应。

对于第二个问题,则需要考虑到瀑布流布局中,元素的上下位置是由它上方元素的高度所决定的。因此,我们需要获取每列中最小的元素高度,并让将要插入的元素放置在当前高度最小的那一列。

算法实现

下面我们就来详细讲解一下如何使用原生JS实现美图瀑布流布局。我们的算法实现分为三个主要的部分:初始化页面、加入新元素以及获取元素的信息。

初始化页面:init()

我们先来看一下如何初始化页面。在此之前,我们需要明确一些参数:

  1. colCount:我们要展示的列数。

  2. colWidth:每一列的宽度。

  3. gap:每一列之间的间隙。

  4. container:存放我们元素的容器。

有了这些参数之后,我们就可以开始初始化页面了。具体来讲,我们需要处理以下几个任务:

  1. 给每一列定位。

  2. 给每一列设置初始高度。

  3. 绑定resize事件,在窗口大小改变的时候重新定位列的位置。

代码实现如下:

let colCount, colWidth, gap, container, columns, itemWidth;

function init(container) {
    colCount = 4;
    colWidth = 200;
    gap = 20;
    columns = [];
    itemWidth = colWidth - 2 * gap; // 减去边距

    // 初始化每一列的位置
    for (let i = 0; i < colCount; i++) {
        let column = document.createElement("div");
        column.className = "column";
        column.style.left = (colWidth + gap) * i + "px";
        container.appendChild(column);
        columns.push(column);
    }

    // 初始化每一列的高度
    reset();

    // 绑定resize事件
    window.addEventListener("resize", () => {
        init(container);
    });
}

function reset() {
    // 初始化每一列的高度
    for (let i = 0; i < colCount; i++) {
        columns[i].style.top = 0;
        columns[i].style.height = 0;
    }
}

加入新元素:add()

有了初始化程序,我们就可以来看一下如何动态地添加元素了。关于如何动态地添加元素,我们可以使用ajax来获取数据,然后通过DOM操作将数据转化为元素,最后加入到我们的容器中。

在这个过程中,我们需要注意几个问题:

  1. 加入元素的时候要考虑到元素的高度,在加入之前我们需要先获取元素的高度。

  2. 加入元素时,我们需要将其放到当前高度最小的那一列,并且要重置该列的高度。

  3. 加入元素完成之后,要重新定位容器的位置,以免出现错列现象。

函数代码如下:

function add(item) {
    let minHeight = columns[0].clientHeight;
    let index = 0;

    // 获取高度最小的列
    for (let i = 0; i < colCount; i++) {
        if (columns[i].clientHeight < minHeight) {
            minHeight = columns[i].clientHeight;
            index = i;
        }
    }

    // 计算item的位置
    let left = colWidth * index + gap * (index + 1);
    let top = minHeight + gap;

    // 新建item,并定位到容器中
    let element = document.createElement("div");
    element.className = "item";
    element.style.width = itemWidth + "px";
    element.style.left = left + "px";
    element.style.top = top + "px";
    element.innerHTML = `<img src="${item.src}" width="${item.width}" height="${item.height}">`;
    columns[index].appendChild(element);

    // 更新高度最小的列的高度
    columns[index].style.height = `${minHeight + element.clientHeight + gap}px`;

    // 更新容器的位置
    container.style.height = `${Math.max(...getColumnHeights())}px`;
}

function getColumnHeights() {
    return columns.map(column => column.clientHeight);
}

获取元素信息:getItemsList()

最后,我们还需要一个函数来获取元素的信息,方便后续的操作。我们可以使用一个for循环来遍历容器中的元素,然后将每一个元素的信息都存储到一个数组中。

function getItemsList() {
    let itemList = [];
    let items = container.querySelectorAll(".item");

    for (let item of items) {
        itemList.push({
            src: item.querySelector("img").src,
            width: item.clientWidth,
            height: item.clientHeight
        });
    }

    return itemList;
}

示例说明

我们来看两个简单的示例说明,展示瀑布流布局的具体实现效果。

示例1:使用Ajax获取数据

// 获取数据
fetch("https://picsum.photos/v2/list")
    .then(response => response.json())
    .then(data => {
        init(document.querySelector(".container"));
        for (let item of data) {
            add({
                src: item.download_url,
                width: item.width,
                height: item.height
            });
        }
    });

该示例展示了如何使用fetch获取数据,然后将数据转化为元素直接加入到容器中。

示例2:使用静态数据

// 静态数据
let data = [
    {
        src: "https://picsum.photos/500/500",
        width: 500,
        height: 500
    },
    {
        src: "https://picsum.photos/400/600",
        width: 400,
        height: 600
    }
];

// 初始化页面
init(document.querySelector(".container"));

// 加入元素
for (let item of data) {
    add(item);
}

该示例展示了如何使用静态数据,直接将数据转化为元素加入到容器中。

总结

通过本文的介绍,我们了解了瀑布流布局的原理和实现方法,掌握了如何使用原生JS实现美图瀑布流布局。使用瀑布流布局可以使我们的页面看起来更加美观,给用户带来更好的体验。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:原生JS实现美图瀑布流布局赏析 - Python技术站

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

相关文章

  • vue中配置mint-ui报css错误问题的解决方法

    问题描述: 在Vue项目中配置Mint UI,import相应的组件后,页面渲染时出现报错,显示缺少相关的CSS文件。 问题原因: 可能是因为在Webpack配置中对CSS进行了特殊处理,导致Mint UI默认的样式文件未能被正确加载。另外,Mint UI依赖于样式文件的引入,如果缺失了相关的CSS文件,会导致组件无法正常使用并报错。 解决方案: 安装相应的…

    css 2023年6月10日
    00
  • css实现三栏布局的几种方法及优缺点

    下面是详细讲解“css实现三栏布局的几种方法及优缺点”的完整攻略。 一、三栏布局 三栏布局指的是一个页面中分别拥有左侧栏、中间栏和右侧栏,其中中间栏宽度固定,左右两栏宽度自适应,三栏均处于同一行。 二、实现方式 1. 使用浮动 使用浮动可以很方便地实现三栏布局,主要是通过给左右两栏设置宽度和浮动属性,然后设置中间栏的宽度和与左右两栏的距离即可。 <di…

    css 2023年6月10日
    00
  • 全面接触神奇的Bootstrap导航条实战篇

    下面是详细的“全面接触神奇的Bootstrap导航条实战篇”的完整攻略: 目录 前言 Bootstrap导航条 实战篇 简单的Bootstrap导航条 响应式Bootstrap导航条 前言 Bootstrap是一个流行的前端开发框架,可以大大加速网页开发的速度。其中,导航条是Web开发中经常使用的组件之一。本文将介绍如何使用Bootstrap创建进行导航条的…

    css 2023年6月11日
    00
  • CSS定义超链接四个状态的正确顺序L-V-H-A

    当我们为网页中的超链接样式定义不同状态时,很容易忘记正确的顺序。使用 CSS 时,正确的顺序是 L-V-H-A,即按照链接的四个状态分别定义 CSS 样式:链接未被访问时(link),鼠标滑过链接时(visited),鼠标悬停在链接上时(hover),以及链接被点击时(active)。下面是详细讲解“CSS定义超链接四个状态的正确顺序L-V-H-A”的完整攻…

    css 2023年6月10日
    00
  • Bootstrap安装环境配置教程分享

    Bootstrap是一款十分流行的响应式前端框架,在进行开发前,我们需要进行Bootstrap的安装和环境配置。下面我将分享一份完整的教程攻略,其中包括Bootstrap的安装和环境配置,以及两条示例说明。 安装和配置Bootstrap 1. 下载Bootstrap 先进入Bootstrap的官网 https://getbootstrap.com/docs/…

    css 2023年6月10日
    00
  • css3中单位px,em,rem,vh,vw,vmin,vmax的区别及浏览器支持情况

    CSS3中常用的单位包括:px、em、rem、vh、vw、vmin、vmax。 px(Pixel) px是相对长度单位,它是绝对单位的一种,表示屏幕上的一个点,通常对应一个物理像素。 px单位的优点是在不同的浏览器下显示效果稳定,但是其缺点是响应式布局使用不便,且在高分辨率显示器中会出现模糊不清的现象。 em em是基于当前字体大小的相对值,例如一个元素的字…

    css 2023年6月10日
    00
  • SpringBoot+Vue开发之Login校验规则、实现登录和重置事件

    我来简单地讲解一下”SpringBoot+Vue开发之Login校验规则、实现登录和重置事件”的攻略。 1. Login校验规则 在前端表单中实现登录功能时,需要考虑以下几个方面的校验规则: 账号不能为空,且长度不应该超过某个特定值 密码不能为空,且长度不应该超过某个特定值 根据用户输入的账号和密码向后端发送请求,验证其是否正确 在具体实现当中,可以使用Vu…

    css 2023年6月10日
    00
  • 理解AngularJs指令

    理解AngularJS指令是掌握AngularJS框架的重要一步。在本篇攻略中,我将向你介绍如何通过实例来深入了解AngularJS指令。以下是步骤: 理解AngularJS指令的基本概念 AngularJS指令是一种特殊的HTML属性,它可以改变HTML元素的行为。指令可以添加新的功能,也可以将HTML元素转化为可重用的组件。 AngularJS指令的语法…

    css 2023年6月9日
    00
合作推广
合作推广
分享本页
返回顶部