前端div块的瀑布流布局

前言

如图,每个类别是一个块。类别个数是动态的,每个类别的条数是动态的,产品经理要求做成图中这样的瀑布流布局。借鉴别人图片的瀑布流布局,来实现这个div块的瀑布流布局。
在这里插入图片描述

开始

对于图片的瀑布流布局来说,有定宽或者定高。我选择定宽的方法。但是在实际情况中,浏览器有多种屏幕宽度,既要给每个div块定宽,又要做到自适应。
所以在这里,
1、我用css计算并设置不同屏幕下div块的宽度:如在>1500宽度下,可以放置5列,除去中间的间距,每列宽度为width:calc(100% - 30px*4)/5;,也就是width:calc(20% - 24px);
2、设置每个div块绝对定位。
3、用js算每个div块的定位位置:第一行div块依次排开;第二行起,每次找高度最小的那一列,填补,再重新计算高度最小的一列,依次填补。
4、由于div块绝对定位,其父元素高度坍塌,用js取最后最高的一列,设置父元素高度。

上代码

html

<ul :style="{height:ulHeight+'px'}" ref="content">
	<li v-for="(item,index) in blockList" 
	    :style="{left:item.left+'px',top:item.top+'px',height:item.height+'px'}" 
	     v-if="item.serviceData.length>0">
			<p>{
   
   {item.typeName}}</p>
			<div class="knowledgeContent">
				<div class="knowledgeItem" 
					 v-for="item1 in item.serviceData" 
					 @click="checkDetail(item,item1)">
						 <i class="itemPoint"></i>
						 <span>{
   
   {item1.title}}</span>	
				</div>
			</div>
	</li>
</ul>

css

ul{
    
    
		position: relative;
		li{
    
    
			width: calc(20% - 24px);
			border: 1px solid #DBDBFD;
			box-shadow: 0 2px 4px 2px #EBEBEB;
			padding-bottom: 10px;
			position: absolute;
			p{
    
    
				height: 50px;
				line-height: 50px;
				padding: 0 15px;
				background: url(../../../assets/img/csManager/knowledgeItemBg.png) ;
				font-family: PingFangSC-Medium;
				font-size: 14px;
				color: #000000;
			}
			.knowledgeContent{
    
    
				.knowledgeItem{
    
    					
					padding: 10px;
					cursor: pointer;
					i{
    
    
						display: inline-block;
						width: 6px;height: 6px;
						border-radius: 50%;
						background: #A7A6DA;
						margin-right: 8px;
						vertical-align: top;
						margin-top: 7px;
						margin-right: 10px;
					}
					span{
    
    
						display: inline-block;
						vertical-align: top;
						width: calc(100% - 25px);
						font-size: 14px;
						color: #000;
					}
					&:hover{
    
    
						i{
    
    
							background: #302e77;
						}
						span{
    
    
							color: #302E77;
						}
					}
				}
			}
		}
	}
@media screen and(max-width:1500px){
    
    
		ul {
    
    
			li{
    
    
				width: calc(25% - 22.5px);
			}
		}
}

javascript

export default {
    
    
	data () {
    
    
		return {
    
    
			colNumbers:0,//列数
			colWidth:0,//块宽度
			colHeight:[],//块高度数据列表,用来查找最小高度,从而实现瀑布流算法
			ulHeight:0,//ul高度(因子元素绝对定位,父元素高度塌陷,故取colHeight最大值加内边距10)
			list:[
				{
    
    typeName:'类别1',
				 seviceData:[{
    
    id:1,title:'标题1'}]
				 }
			],
			blockList:[],//含有定位位置的列表,用来循环显示
		}
	},
	methods:{
    
    
		//计算块列数,>1500时为5列,<=1500 时,为4列,间距为30
		getColNumbers() {
    
    
			let screenwidth = document.documentElement.clientWidth;
			if(screenwidth>1500){
    
    
				this.colNumbers = 5;
				this.colWidth = (this.$refs.content.clientWidth - 30*4)/5;
			}else{
    
    
				this.colNumbers = 4;
				this.colWidth = (this.$refs.content.clientWidth - 30*3)/4;
			}			
		},
		//读取块,设置高度信息
		loadBlock() {
    
    
			this.getColNumbers();
			for(let i =0; i < this.list.length; i++){
    
    
				//1.求本块高度
				let height = 80;
				this.list[i].serviceData.forEach(item=>{
    
    
					if(item.title.length>15){
    
    //标题超过15字,换行,此条高度为62px(标题限制为20字)
						height+=62;
					}else{
    
    
						height+=41;
					}
				})
				//2.传参调用方法
				this.render({
    
    
					index:i,
					height:height,
					...this.list[i]
				})
			}
			//3.因子元素全部绝对定位,父元素高度用js计算得到,取高度最大值
			this.ulHeight =  Math.max.apply(null, this.colHeight);
		},
		//设置渲染块的list
		render(blockInfo){
    
    
			let colIndex = blockInfo.index % this.colNumbers;		
			
			if (blockInfo.index < this.colNumbers) {
    
    //首行:top为 0,记录每列的高度
				blockInfo.top = 0
				this.colHeight[colIndex] = blockInfo.height;
				blockInfo.left = colIndex == 0? colIndex * this.colWidth :(colIndex * this.colWidth+30*colIndex) ;
			} else {
    
    
				//获取高度的最小值
				let minHeight = Math.min.apply(null, this.colHeight)
				let minIndex = this.colHeight.indexOf(minHeight)
				//此块的 top 为上面块的高度,left 相等
				blockInfo.top = minHeight + 30;
				let minColIndex = minIndex % this.colNumbers;//计算最小的在哪一列
				blockInfo.left = minColIndex == 0? minColIndex * this.colWidth :(minColIndex * this.colWidth+30*minColIndex) ;
				//把高度加上去
				this.colHeight[minIndex] +=  30+blockInfo.height;
			}
			this.blockList.push(blockInfo)
			
		}
	}

结束

在此记录问题,如有需要修改的地方,还请不吝赐教。文章借鉴:手把手带你撸瀑布流布局的5种实现方式

猜你喜欢

转载自blog.csdn.net/qq_39352780/article/details/118155077