BOYYANG/1/blog/长发美女 鲜花 白色裙子4K壁纸3840_2160_彼岸图网

如何实现瀑布流效果

作者: boyyang
分类: 后端开发
发布: 2024-04-10 05:02:13
更新: 2025-03-31 05:40:30
浏览: 134

       前端做瀑布流可以通过多种方式,最简单的是通过cloumn-count属性来做,但是这种最大的缺陷便是图片加载方式是从左到右加载的,如果是图片固定那么便没有问题,但是如果图片有分页,触底加载。那么就不是很好了。

       所以通过绝对定位动态计算每一张图片的位置,是目前最好的方案,涉及到动态计算图片位置,那么前提条件得获取到dom元素,但是这样图片懒加载便会有问题。但是这也是没有办法的事情。

       除此之外还有一种方式便是后端返回图片尺寸信息,前端获取数据后通过数据来计算,也就省去了前端获取dom这一步骤,图片懒加载的问题也就解决了。当然如果后端没有记录图片上传时的尺寸,那么还是得老老实实获取dom元素吧。

       由于后端也是我写的,所以我强烈要求后端在图片上传的时候,获取图片的尺寸并记录进数据库中,所以也就可以省去获取dom这一步了。

       有后端加持下,具体步骤如下:(没有后端加持,其实思路也相似)

interface IData {
    name: string;
    width: number;
    height: number;
}

type IRData = IData & { w: number, h: number, x: number, y: number }

const data: IData[] = [
    {
        name: '图片1',
        width: 4000,
        height: 1500,
    },
    {
        name: '图片2',
        width: 3000,
        height: 700,
    },
    {
        name: '图片3',
        width: 4000,
        height: 1000,
    },
    {
        name: '图片1',
        width: 1900,
        height: 600,
    },
]

/*
* row 每一行放多少图片
* gap 图片之间间隙
* data 后端数据
* screenWidth 盒子宽度 
* */
const waterfallFlow = (row: number, gap: number, screenWidth: number, data: IData[]): IRData[] => {
    // 根据屏幕宽度计算图片能占多少宽度
    const imageWidth = (screenWidth - ((row - 1) * gap)) / row
    // 初始化数组用了记录当前各列目前高度 方便计算下一张图片的位置
    const currentHeightArr = Array.from({length: row}, () => 0)

    return data.map((d, i) => {
        // 计算图片比例 方便算出 图片高度
        const imageHeight = imageWidth * (d.height / d.width)

        if (i < row) { // 第一行图片单独处理
            const x = i * (imageWidth + gap)
            // 记录当前各列高度
            currentHeightArr[i] = imageHeight + gap
            return {
                ...d,
                w: imageWidth, //这是计算出的渲染宽度
                h: imageHeight, //这是计算出的渲染高度
                x: x, // x定位
                y: 0, // y定位 第一行y轴固定为0
            }
        } else {
            // 获取记录数组的最小值下标
            const minIndex = currentHeightArr.indexOf(Math.min(...currentHeightArr))
            const x = minIndex * (imageWidth + gap)
            const y = currentHeightArr[minIndex]
            // 记录当前各列高度 当前高度 + 图片高度 + gap
            currentHeightArr[minIndex] = currentHeightArr[minIndex] + imageHeight + gap
            return {
                ...d,
                w: imageWidth,
                h: imageHeight,
                x: x,
                y: y,
            }
        }
    })
}


#前端
#后端
#瀑布流