什么???你竟然学会了用js写瀑布流

25 阅读3分钟

这是一篇给大学生正在学js看的,工作了的不用看了,为什么不用看呢,因为我怕被你们笑,而我这篇文章只能给清澈而又清澈的大学生,莫笑莫笑。 在很多特效中,我们会看到轮播图,计时器这类的特效,然而深究他的原理都会发现是在操作dom之类的,然后用算法的思维去计算,当然这篇文章的也是。 这篇文章的核心算法是主要获取每列的最小高度,然后将图片放在最小的高度中,其他的就没有了。 代码都已经贴,图片的话,大家自己网上找就好,然后不懂的再评论区讨论

// 先贴一下用算法计算他的最小高度
const getMinHeight = (arr) => {
    // 第一种算法
    const minHeight = arr[0];
    for(let i = 0, length = arr.length; i < length; i++) {
        if(arr[i] < minHeight) {
            minHeight = arr[i];
        }
    }
    return minHeight;
    // 第二种 算法 
    // return Math.min(...arr)
    // 第三种算法
    // return Math.min.call(null, arr)
}

// 然后设置图片的位置
const setPositions () => {
    const {
        columns,
        space
    } = getColumns();
    const arr = new Array(columns).fill(0); // 定义列高数组并初始化为0
    const imgs = container.querySelectorAll("#container img"); // 获取所有图片元素
    for (let i = 0; i < imgs.length; i++) {
        const img = imgs[i]; // 获取当前的图片
        const minTop = getMinHeight(arr); // 获取当前图片的最小高度
        const index = arr.indexOf(minTop); // 获取最小高度的索引
        arr[index] += img.height + space; // 更新对应列的高度
        const left = (index + 1) * space + index * imgWidth; // 设置图片的left值
        img.style.transform = `translate(${left}px, ${minTop}px)`; // 使用transform设置位置
    }
    maxHeight = getMaxHeight(arr); // 获取最大高度
}

废话不多说,我直接贴源码吧,不懂的,评论上讨论哈哈哈哈

css 代码
* {
    padding: 0px;
    margin: 0px;
}
.container {
    margin: 20px auto;
    width: 90%;
    height: 100%;
    position: relative;
    border: 1px solid #ccc;
}
.container img {
    position: absolute;
    transition: all 0.3s ease;
}
js 代码
// 获取最小值
const getMinHeight = arr => {
    return Math.min.call(null, ...arr)
}
// 获取最大值
const getMaxHeight = arr => {
    return Math.max.call(null, ...arr)
}

// 定义一个防抖函数
const debounce = (func, dealy) => {
    let timer = null;
    return function (...args) {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            func.apply(this, args)
        }, dealy);
    }
}
const container = document.querySelector("#container")
// 定义常量值
const imgWidth = 220
let maxHeight = 0

// 获取返回列数
const getColumns = arr => {
    const containerWidth = container.clientWidth; // 获取容器宽度
    const columns = Math.floor(containerWidth / imgWidth); // 计算列数
    const extraSpace = containerWidth - columns * imgWidth; // 计算剩余宽度
    const spaceNum = columns + 1; // 间距数量
    const space = Math.floor(extraSpace / spaceNum); // 计算间距
    return {
        columns,
        space
    }
}
// 设置图片位置
const setPositions = () => {
    const {
        columns,
        space
    } = getColumns();
    const arr = new Array(columns).fill(0); // 定义列高数组并初始化为0
    const imgs = container.querySelectorAll("#container img"); // 获取所有图片元素
    for (let i = 0; i < imgs.length; i++) {
        const img = imgs[i]; // 获取当前的图片
        const minTop = getMinHeight(arr); // 获取当前图片的最小高度
        const index = arr.indexOf(minTop); // 获取最小高度的索引
        arr[index] += img.height + space; // 更新对应列的高度
        const left = (index + 1) * space + index * imgWidth; // 设置图片的left值
        img.style.transform = `translate(${left}px, ${minTop}px)`; // 使用transform设置位置
    }
    maxHeight = getMaxHeight(arr); // 获取最大高度
}

const createImage = () => {
    const fragment = document.createDocumentFragment() // 添加文档碎片留
    for (let i = 1; i <= 17; i++) {
        const img = document.createElement("img")
        if (i < 10) {
            img.src = `./images/0${i}.jpg`
        } else {
            img.src = `./images/${i}.jpg`
        }
        img.style.width = `${imgWidth}px`
        img.onload = setPositions
        fragment.appendChild(img)
    }
    container.appendChild(fragment);
    container.style.height = `${maxHeight}px`;
}

// 监听窗口变化
const bindEvent = () => {
    const handleResize = () => {
        setPositions();
        container.style.height = `${maxHeight}px`;
    };

    const debouncedHandleResize = debounce(handleResize, 500);
    window.addEventListener("resize", debouncedHandleResize);
}
// 主函数入口
const main = () => {
    createImage();
    bindEvent();
}

main()

html代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片瀑布流</title>
    <style></style>
    <link rel="stylesheet" href="./css/index.css" preload />
    <script src="./js/index.js" defer></script>
</head>

<body>
    <div class="container" id="container"></div>
</body>

</html>