原生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日

相关文章

  • css实现中间文字两边横线效果

    要实现中间文字两边横线的效果,可以使用CSS中的伪元素 ::before 和 ::after,以及border-bottom实现。具体的实现方式如下: 首先需要在HTML中添加需要添加效果的元素,例如下面的代码,我们在h1标签中添加示例文本: <h1>This is an example text</h1> 然后,在CSS中为该元素添…

    css 2023年6月10日
    00
  • 利用vue重构有赞商城的思路以及总结整理

    下面我来详细讲解利用Vue重构有赞商城的思路以及总结整理的完整攻略。 思路 1. 页面结构化 在进行重构之前,我们首先需要对页面进行结构化,将不同的组件、页面模块进行归类,确定其在页面中的位置以及相互之间的依赖关系。 2. 数据管理 在Vue中,我们使用Vuex来管理数据,因此需要对商城中的数据进行分析,并设计Vuex的状态管理方案。 3. 视图组件 将页面…

    css 2023年6月10日
    00
  • 高性能WEB开发 页面呈现、重绘、回流。

    高性能WEB开发是一个需要深入研究和掌握的领域,其中涉及到的大量知识技能和技术工具要求开发者有扎实的理论基础和丰富的实战经验。在这篇文章中,我们将着重讨论三个重要的主题:页面呈现、重绘和回流。这些主题与前端开发的性能相关,并且会影响用户对网站的使用体验。 一、页面呈现 页面呈现是指在浏览器中加载并显示网页的过程。在页面呈现的过程中,浏览器会将HTML、CSS…

    css 2023年6月10日
    00
  • css教程:选择合适的、有意义的元素描述内容

    选择合适的、有意义的元素描述内容是CSS在前端开发中的重要指导原则之一。简单来说,就是在HTML代码中选择合适的HTML元素,并使用CSS对其进行样式修饰,从而让页面结构更加清晰、易读、易维护。下面是详细的攻略: 1. 选择合适的HTML元素 在HTML中,我们可以利用各种标签来描述网页的结构和内容,如 、 、 、 等。选择合适的HTML元素可以提高页面的可…

    css 2023年6月10日
    00
  • 前端面试必备之CSS3的新特性

    我来讲解一下。 前端面试必备之CSS3的新特性 1. CSS3的属性选择器 在CSS3中,新增了一些属性选择器,让选择元素更加灵活方便。下面介绍两种常用的属性选择器: 1.1 属性存在选择器 语法:[attribute] 这个选择器可以匹配指定属性的元素。例如: input[type] 这段代码选择所有具有”type”属性的input元素。如果我们想匹配所有…

    css 2023年6月9日
    00
  • 如何利用CSS3制作3D效果文字具体实现样式

    以下是关于“如何利用CSS3制作3D效果文字具体实现样式”的完整攻略,包含两个示例说明。 制作3D效果文字的具体实现样式 CSS3提供了一些新的3D效果样式,可以用来制作3D效果文字。以下是一些常用的3D效果样式: 1. transform-style transform-style属性用于指定3D变换的子元素如何在3D空间中呈现。可以使用CSS的trans…

    css 2023年5月18日
    00
  • css图标制作教程制作云图标

    下面我会详细讲解如何制作云图标的完整攻略,包含以下几个步骤: 1. 准备工作 在制作过程中,我们需要准备两个东西,一是云的SVG图标文件,二是实现动画效果的CSS代码: (1)SVG图标文件: 首先需要使用Adobe Illustrator或其他矢量图形编辑软件,设计并导出一个云的SVG图标文件,示例如下: <svg width="24px&…

    css 2023年6月10日
    00
  • css设置矢量图字体图标的方法(图解)

    下面是详细讲解 “CSS设置矢量图字体图标的方法(图解)” 的完整攻略。 什么是矢量图字体图标? 矢量图字体图标是一种使用 CSS 的方式来显示图标的方法。它使用字体文件,其中包含了一组图标,这些图标都是使用矢量图形进行绘制的。当需要显示某个图标时,我们可以通过设置 CSS 样式,使用相应的字体图标类名来实现在页面上显示该图标的目的。 如何设置矢量图字体图标…

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