一、思路
1、获取可视容器宽,设置相对定位;
2、设置单个卡片默认宽,高自适应,设置绝对定位;
3、获取卡片DOM实例;
4、根据1/2获取一行可以放多少个卡片(同时按一行卡片个数设置宽自适应);
5、所有的卡片top/left初始化为0;
6、设置第一行的位置,即top=0,left的值,同时获取第一行的卡片高;
7、第二行开始插入卡片,获取第一行高度最小的卡片位置下插入,left同值,同时替换当前高度为当前卡片高度+同位置上面卡片的高度;
二、实现
<div class="main-content">
<div class="main-content-item">卡片1</div>
<div class="main-content-item">卡片2</div>
<div class="main-content-item">卡片3</div>
<div class="main-content-item">卡片4</div>
<div class="main-content-item">卡片5</div>
<div class="main-content-item">卡片6</div>
</div>
.main-content {
width: 100%;
height: 100%;
overfllow: hidden auto;
position: relative;
&-item {
width: 350px;
position: absolute;
top: 0;
left: 0;
}
}
/**
* 数据处理-卡片位置计算
* TODO 数据量大时分页渲染
* */
handlerData(){
// 1、获取容器宽
let contentWidth = document.getElementsByClassName('main-content')[0].clientWidth;
// 2、卡片
let div = document.getElementsByClassName('main-content-item')
// 初始卡片宽、边距
let normalWidth = 350 , padding = 16
// 每排可以放多少个
let page = Math.floor((contentWidth) / normalWidth)
// 自适应宽
let nowWidth = contentWidth / page
// 初始化left、top
for (let i = 0; i < div.length; i++) {
div[i].style.cssText= `left:0;top:0;`
}
let divHeight = []
// 设置第一排的width、left
for (let i = 0; i < page; i++) {
if(!div[i]) break;// 少于1行退出循环
divHeight.push(div[i].clientHeight)
div[i].style.cssText = `width:${nowWidth - padding + 'px'};left:${i * nowWidth + 'px'};`
}
// 大于1行计算top/left/width
if(div.length <= page) return;
// 其他卡片的top、left
for (let i = page; i < div.length; i++) {
let min_height = Math.min.apply(Math, divHeight), // 获取到数组中最小top
min_index = divHeight.indexOf(min_height)// 查找到最小高度卡片的下标
div[i].style.width = nowWidth - padding + 'px';
div[i].style.left = div[min_index].style.left // 当前卡片和最小高度卡片的left值相同
div[i].style.top = min_height + padding + 'px'
// 替换的高度 = 上一个卡片的top + 最小高度卡片的height + 间隙
divHeight[min_index] = min_height + div[i].clientHeight + padding
}
}