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

yizhihongxing

标题:原生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中的line-height行高属性学习教程

    下面为您详细讲解“CSS中的line-height行高属性学习教程”的完整攻略。 什么是line-height? line-height(行高)是CSS中的一个属性,它用于设置文字行与行之间的距离,更为准确的说是行框盒模型中相邻的两个框之间的距离。 line-height的语法 line-height的语法非常简单,可以使用单位或者无单位,如下所示: /* …

    css 2023年6月10日
    00
  • vue或css动画实现列表向上无缝滚动

    下面是“vue或css动画实现列表向上无缝滚动”的完整攻略。 使用CSS3动画实现列表向上无缝滚动 CSS3中,有一个属性叫做animation,可以帮助我们实现动画效果。我们可以通过设置CSS动画的参数和关键帧来实现向上无缝滚动的效果。 1. HTML结构 我们需要一个UL和若干个LI实现一个向上无缝滚动的列表,如下所示: <ul class=&qu…

    css 2023年6月10日
    00
  • 拖动table标题实现改变td的大小(css+js代码)

    实现拖动表格标题来改变表格单元格的大小需要使用HTML、CSS和JavaScript进行组合实现。 HTML代码 首先,我们需要使用HTML创建一个表格,每个单元格都包含一个div元素,用于拖动边界。 <table> <thead> <tr> <th><div class="resize&quo…

    css 2023年6月10日
    00
  • CSS网页布局:div水平居中的各种方法

    下面我为你详细讲解“CSS网页布局:div水平居中的各种方法”的完整攻略。 方法一:使用text-align属性 text-align属性可以用于水平对齐元素的内容,其取值包括left、center和right。如果将该属性用于div元素,那么该元素的所有内容都会水平居中。 示例代码: <!DOCTYPE html> <html> &…

    css 2023年6月10日
    00
  • 利用CSS中的 outline-offset 属性实现加号

    利用 CSS 中的 outline-offset 属性可以实现一些有趣的效果,其主要作用是设置轮廓(outline)相对于边框(border)的偏移量(offset)。下面是实现加号的具体步骤: 创建一个正方形的容器 我们可以使用 div 标签来创建一个正方形的容器,并为其设置 width、height、background-color 和 border: …

    css 2023年6月10日
    00
  • Dreamweaver怎么插入水平线并设置颜色?

    插入水平线并设置颜色是Dreamweaver中基本的排版样式之一,下面是此操作的详细攻略: 步骤一:打开Dreamweaver并选择需要插入水平线的位置 在Dreamweaver中打开需要插入水平线的网页文件,然后在需要插入水平线的位置点击鼠标光标。 步骤二:插入水平线 在页面顶部的“插入”菜单中,找到“水平线”选项并点击。也可以使用快捷键Ctrl+Shif…

    css 2023年6月9日
    00
  • PC端和移动端自适应问题的快速解决方法

    针对PC端和移动端自适应问题的解决方法,我提供以下完整攻略: 1. 使用响应式设计 响应式设计是指利用media query查询技术来确保网站可在各种终端设备上正常显示,其核心原则就是使用相对单位(如%、em等)代替固定单位(如px),同时使用@media规则在不同的屏幕尺寸下(如768px、992px等)使用不同的样式效果。 在实践中,我们可以采用流式布局…

    css 2023年6月10日
    00
  • 父级元素未设置高度和宽度时高度塌陷问题的解决方法

    父级元素未设置高度和宽度时,如果其内部的子元素设置了浮动或者绝对定位等导致元素脱离文档流的属性,会造成父级元素高度塌陷问题。那么该如何解决父级元素高度塌陷的问题呢?下面我们提供两种具体的解决方法。 方法一:使用clearfix清除浮动 当子元素使用浮动属性后,父元素的高度无法被撑开,导致造成高度塌陷。此时可以使用clearfix这个类来进行清除浮动。 示例代…

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