import { pxToVw } from './num'
/**
* 瀑布布局
* @param parent 父盒子
* @param colNum 多少列
* @param wgap 宽度间隔 单位是vw
* @param hgap 高度间隔 单位是vw
* @returns 返回父盒子的高度 绝对定位会导致高度塌陷
*/
export const waterFall = (
parent: Element | HTMLDivElement,
colNum: number,
wgap: number,
hgap: number
) => {
// 所有card的div
const childrenElements = parent.children as unknown as HTMLDivElement[]
// 初始化每一行的高度 用于布局时的top,默认为0
const childrenHeightArr = Array.from<number>({ length: colNum }).fill(0)
// card的宽度
const cardWidth = pxToVw(childrenElements[0].offsetWidth)
for (const child of childrenElements) {
// 拿到最小高度 以及 对应的index
const minHeight = Math.min.apply(null, childrenHeightArr)
const minIndex = childrenHeightArr.indexOf(minHeight)
// 设置当前card位置,整体逻辑为不断的向高度最小的位置插入card,类似于俄罗斯方块
child.style.position = 'absolute' // style设置样式
child.style.top = `${minHeight}vw`
child.style.left = `${cardWidth * minIndex + (minIndex ? wgap : 0)}vw`
// 不断更新记录的高度
childrenHeightArr[minIndex] += pxToVw(child.offsetHeight) + hgap
}
return {
parentHeight: Math.max.apply(null, childrenHeightArr)
}
}
瀑布流大部分都是定宽的 所以列数可以预知. 我的适配用的vw,rem的适配切换下单位转换函数即可.没有适配直接删除pxToVw的使用.