
如何实现瀑布流效果
作者: 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,
}
}
})
}