瀑布流_瀑布流布局 - CSDN
瀑布流 订阅
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格。 展开全文
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格。
信息
简    介
瀑布流,又称瀑布流式布局
外文名
waterfall flow
特    点
琳琅满目:整版以图片为主
词    性
名词
中文名
瀑布流
瀑布流特点
1、琳琅满目:整版以图片为主,大小不一的图片按照一定的规律排列。2、唯美:图片的风格以唯美的图片为主。 3、操作简单:在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前。
收起全文
精华内容
参与话题
  • 3种方式实现瀑布流布局

    万次阅读 多人点赞 2019-08-15 10:07:16
    今天逛闲鱼的时候观察到每一行的高度不是相同的,经了解才知道原来这是一种瀑布流布局,感觉挺有意思,于是决定研究一下,在网上也找了一些方案,实现瀑布流大概有3种方式。

    前言

    今天逛闲鱼的时候观察到每一行的高度不是相同的,经了解才知道原来这是一种瀑布流布局,感觉挺有意思,于是决定研究一下,在网上也找了一些方案,实现瀑布流大概有3种方式。

    一、JS 实现瀑布流

    思路分析

    1. 瀑布流布局的特点是等宽不等高。
    2. 为了让最后一行的差距最小,从第二行开始,需要将图片放在第一行最矮的图片下面,以此类推。
    3. 父元素设置为相对定位,图片所在元素设置为绝对定位。然后通过设置 top 值和 left 值定位每个元素。

    代码实现

    <!DOCTYPE html>
    <html>
    <head>
        <style>
            .box {
                width: 100%;
                position:relative;
            }
            .item {
                position: absolute;
            }
            .item img{
                width: 100%;
                height:100%;
            }
        </style>
    </head>
    <body>
    <div class="box">
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
    </div>
    </body>
    <script src="jquery.min.js"></script>
    <script>
        function waterFall() {
            // 1 确定图片的宽度 - 滚动条宽度
            var pageWidth = getClient().width-8;
            var columns = 3; //3列
            var itemWidth = parseInt(pageWidth/columns); //得到item的宽度
            $(".item").width(itemWidth); //设置到item的宽度
            var arr = [];
            $(".box .item").each(function(i){
                var height = $(this).find("img").height();
                if (i < columns) {
                    // 2 第一行按序布局
                    $(this).css({
                        top:0,
                        left:(itemWidth) * i+20*i,
                    });
                    //将行高push到数组
                    arr.push(height);
                } else {
                    // 其他行
                    // 3 找到数组中最小高度  和 它的索引
                    var minHeight = arr[0];
                    var index = 0;
                    for (var j = 0; j < arr.length; j++) {
                        if (minHeight > arr[j]) {
                            minHeight = arr[j];
                            index = j;
                        }
                    }
                    // 4 设置下一行的第一个盒子位置
                    // top值就是最小列的高度
                    $(this).css({
                        top:arr[index]+30,//设置30的距离
                        left:$(".box .item").eq(index).css("left")
                    });
    
                    // 5 修改最小列的高度
                    // 最小列的高度 = 当前自己的高度 + 拼接过来的高度
                    arr[index] = arr[index] + height+30;//设置30的距离
                }
            });
        }
        //clientWidth 处理兼容性
        function getClient() {
            return {
                width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
                height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
            }
        }
        // 页面尺寸改变时实时触发
        window.onresize = function() {
            //重新定义瀑布流
            waterFall();
        };
        //初始化
        window.onload = function(){
            //实现瀑布流
            waterFall();
        }
    </script>
    </html>
    

    效果如下
    图片是

    二、column 多行布局实现瀑布流

    思路分析:

    column 实现瀑布流主要依赖两个属性。
    一个是 column-count 属性,是分为多少列。
    一个是 column-gap 属性,是设置列与列之间的距离。

    代码实现:

    <!DOCTYPE html>
    <html>
    <head>
        <style>
            .box {
                margin: 10px;
                column-count: 3;
                column-gap: 10px;
            }
            .item {
                margin-bottom: 10px;
            }
            .item img{
                width: 100%;
                height:100%;
            }
        </style>
    </head>
    <body>
    <div class="box">
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
    </div>
    </body>
    

    效果如下:
    在这里插入图片描述

    三、flex 弹性布局实现瀑布流

    思路分析:

    flex 实现瀑布流需要将最外层元素设置为 display: flex,即横向排列。然后通过设置 flex-flow:column wrap 使其换行。设置 height: 100vh 填充屏幕的高度,来容纳子元素。每一列的宽度可用 calc 函数来设置,即 width: calc(100%/3 - 20px)。分成等宽的 3 列减掉左右两遍的 margin 距离。

    代码实现:

    <!DOCTYPE html>
    <html>
    <head>
        <style>
            .box {
              display: flex;  
              flex-flow:column wrap;
              height: 100vh;
            }
            .item {
                margin: 10px;
                width: calc(100%/3 - 20px);
            }
            .item img{
                width: 100%;
                height:100%;
            }
        </style>
    </head>
    <body>
    <div class="box">
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="show.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="cloth.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="banner.jpg" alt="" />
        </div>
    </div>
    </body>
    

    效果如下:
    在这里插入图片描述

    四、3种方式对比

    如果只是简单的页面展示,可以使用 column 多栏布局和 flex 弹性布局。如果需要动态添加数据,或者动态设置列数,就需要使用到 JS + jQuery。

    展开全文
  • 浅析瀑布流布局及其原理

    万次阅读 2018-12-20 09:53:20
    一、什么是瀑布流 很多时候我们会看到一些Vlog网站或者展示图片的网站,它们的图片明明每一张的高度大小都不同,但是却能自动地适应,排成一行一行地展示,并且下拉到底的时候,加载的图片也会自动适应,这就是瀑布...

    一、什么是瀑布流

    很多时候我们会看到一些Vlog网站或者展示图片的网站,它们的图片明明每一张的高度大小都不同,但是却能自动地适应,排成一行一行地展示,并且下拉到底的时候,加载的图片也会自动适应,这就是瀑布流,比如下图。
    可以清晰地看到,红色框住的图片大小不一样,却能自动适应排列

    二、实现原理

    要做到每一张图片都根据上面的高度自动适应排列,那么我们就不能单纯地靠html+css布局了,需要用到js来帮助计算位置(其实用CSS3也能布局)。那么计算什么呢?

    首先,我们需要理清一个思路,就是这个布局是按一列列来看的,如下图:
    在这里插入图片描述
    我们要做的,其实就是在每一列下面插入新的图片,这样它就会紧挨着上面的图片对齐。至于上面和下面的图片间距,那么很自然地是利用了margin和padding属性,不熟悉盒子属性的可以移步去理解padding和margin,等于理解了盒子模型这篇文章看看。

    三、事先准备

    • 建议事前在网上随便下载15张以上的图片,不用理会长宽问题,这些都是可以用css设置的;
    • 准备好jQuery
    • 然后按照以下布局去把HTML结构和CSS样式写好:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<meta http-equiv="X-UA-Compatible" content="ie=edge">
    	<link rel="stylesheet" href="css/index.css">
    	<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    	<script src="js/index.js"></script>
    
    	<title>Document</title>
    </head>
    <body>
    	<div id="wrap" class="wrap">
    		<div class="item"> <img src="images/1.jpg" alt=""> </div>
    		<div class="item"> <img src="images/2.jpg" alt=""> </div>
    		<div class="item"> <img src="images/3.jpg" alt=""> </div>
    		<div class="item"> <img src="images/4.jpg" alt=""> </div>
    		<div class="item"> <img src="images/5.jpg" alt=""> </div>
    		<div class="item"> <img src="images/6.jpg" alt=""> </div>
    		<div class="item"> <img src="images/7.jpg" alt=""> </div>
    		<div class="item"> <img src="images/8.jpg" alt=""> </div>
    		<div class="item"> <img src="images/9.jpg" alt=""> </div>
    		<div class="item"> <img src="images/10.jpg" alt=""> </div>
    		<div class="item"> <img src="images/11.jpg" alt=""> </div>
    		<div class="item"> <img src="images/12.jpg" alt=""> </div>
    		<div class="item"> <img src="images/13.jpg" alt=""> </div>
    		<div class="item"> <img src="images/14.jpg" alt=""> </div>
    		<div class="item"> <img src="images/15.jpg" alt=""> </div>
    		<div class="item"> <img src="images/16.jpg" alt=""> </div>
    		<div class="item"> <img src="images/17.jpg" alt=""> </div>
    		<div class="item"> <img src="images/18.jpg" alt=""> </div>
    		
    	</div>
    </body>
    </html>
    

    css样式:

    *{
        margin: 0;
        padding: 0;
        border:none
    }
    body{
        background: #ddd
    }
    .wrap{
        width: auto;
        height: auto;
        position: relative;
        margin:0 auto;
    }
    .item{
        float: left;
        width: 280px;
        height: auto;
        padding: 10px;
        margin: 10px;
        box-sizing: border-box;
    }
    
    .item img{
        display: block;
        width:100%;
        border-radius: 10px;
        cursor: pointer;
    }
    .item img:hover{
        background-color: gray;
        opacity: 0.5;
    }
    

    至此,那么你的第一排就已经布局好了,接下来我们就是要用js去计算一页能有多少列图片以及如何在每一列里面插入新图片。

    四、瀑布流的核心

    实现瀑布流的核心其实就两个:

    • 找出图片高度最小的那一列,再那一列插入,然后继续找下一个高度最小的,一直循环直到插满图片为止;
    • 计算出每一列距离浏览器整体的距离,也就是position里的leftright,有什么用呢?当你知道某一列的left的时候,相当于就知道了在它下面插入图片时,图片如何定位到这一列了,只要图片的left值和列是一样的,那么图片自然就插入到列里面了

    实现代码如下:

    var data=[
        {"src":"1.jpg"},
        {"src":"2.jpg"},
        {"src":"3.jpg"},
        {"src":"4.jpg"},
        {"src":"5.jpg"},
        {"src":"6.jpg"},
        {"src":"7.jpg"},
        {"src":"8.jpg"},
        {"src":"9.jpg"},
        {"src":"10.jpg"},
        {"src":"11.jpg"},
        {"src":"12.jpg"},
        {"src":"13.jpg"},
        {"src":"14.jpg"},
        {"src":"15.jpg"},
        {"src":"16.jpg"},
        {"src":"17.jpg"},
        {"src":"18.jpg"},
    ]
    
    $(function(){
        var wrap=$('#wrap');
        var boxes=wrap.children("div");
        waterfall(wrap,boxes);
        $(this).scroll(function(event){
            appendBox(wrap,boxes)
        })
    })
    // 主要瀑布流布局函数
    function waterfall(wrap,boxes){
    // 第一步:先获取能容纳的列数:窗口宽度/每列宽度
    // +20是外边距
    var boxswidth=boxes.eq(0).width()+40;
    var windowwidth=$(window).width();
    var column=Math.floor(windowwidth/boxswidth);
    // 顺便计算得出容器的宽度,让盒子居中
    var wrapwidth=column*boxswidth;
    wrap.width(wrapwidth)
    // 第二步:定义一个数组存储每一列的高度
    var arr=new Array;
    // 遍历每一个盒子
    for(var i=0;i<boxes.length;i++){
        // 当i<column时,说明在第一行,把盒子的高度存入到数组里
        if(i<column){
            arr[i]=boxes.eq(i).height()+40
        }
        // 否则就是第二行,开始按最小高度插入图片到列中
        else{
            // 先获取最小高度列的索引
            var minheight=Math.min.apply(null,arr)
            var minindex=getMinIndex(minheight,arr)
            // 这里的leftvalue,是指最小高度列距离窗口左边的距离,相当于间接定位了这一列接下来要插入图片时,position定位的left值是多少
            var leftvalue=boxes.eq(minindex).position().left;
            setStyle(boxes.eq(i),minheight,leftvalue,i)
            // 到这里已经插入了一张图片在最低高度列,接下来要改变arr里的最低高度的值,让它继续下次遍历
            arr[minindex]+=boxes.eq(i).height() + 20
        }
    }
    }
    
    //设置追加盒子的样式  减少刷新量
       var getStartNumber=0;
       var setStyle=function(box,top,left,index){
           if(getStartNumber>=index){
               return false;
           };
         box.css({
             'position':'absolute',
             'top':top,
             'left':left,
             'opacity':'0'
         })  .stop().animate({/*第二行慢慢出来的动画*/
             'opacity':'1'
         },1000);
           getStartNumber=index;
       };
    
    
    // 计算最小高度列的索引函数
    function getMinIndex(minheight,arr){
        var minindex=arr.indexOf(minheight)
        return minindex
    }
    
    // 判断是否在底部的函数
    function getBottom(wrap){
        // 获取最后一列的高度和滚动的高度+窗口高度的和,如果长的一列的高度比窗口+滚动的高度要小,说明到底了需要追加
        var documentHeight=$(window).height();
        var scrollHeight=$(window).scrollTop();
        var boxes = wrap.children('div')
        var lastboxTop=boxes.eq(boxes.length-1).offset().top;
        var lastboxHeight=boxes.eq(boxes.length-1).height()+20;
        var totalHeight=lastboxHeight+lastboxTop
        return documentHeight+scrollHeight>=totalHeight?true:false;
    }
    
    // 追加瀑布流效果
    function appendBox(wrap,boxes){
        // 先判断是否展示到了底部
        if(getBottom(wrap)){
            for (i in data){
                var addstr="<div class='item'> <img src='images/"+data[i].src+"' alt=''> </div>"
                wrap.append(addstr)
            }
        }else{
            return false
        }
        waterfall(wrap,wrap.children('div'))
    }
    

    注意:这里面我还加入了瀑布流追加的效果,就是下拉到底会自动加载,不过图片是重复的,需要在js顶部先定义一组数据,用来替换生产<img>里src,至于实现原理,不是本文重点,大家可以通过注释去尝试理解

    展开全文
  • 瀑布流效果(图片自适应)

    千次阅读 2019-02-27 19:23:54
    上学期进行了一次swift实训,组里的小姐姐们说能不能用瀑布流的效果,开始我以为和通讯录那种行表式差不多,查看xcode里面有没有支持这种效果的方法,但是找了很久没有找到。于是准备自己动手,code了一天,但是还是...

    上学期进行了一次swift实训,组里的小姐姐们说能不能用瀑布流的效果,开始我以为和通讯录那种行表式差不多,查看xcode里面有没有支持这种效果的方法,但是找了很久没有找到。于是准备自己动手,code了一天,但是还是没有弄出来,在组里大佬的提醒下,我意识到我没有必要自己造轮子,可以用别人写好的。于是推荐了我一个很好的网站:代码库,里面有许多别人做好的案例。
    于是我开始进行搜索瀑布流相关的代码,但是我下载了许多来运行的时候发现有许多是object-C来写,和swfit混用有点让人难受。当我找到一些用swfit写的瀑布流案例后,发现有些代码逻辑太乱,有些又写的很复杂,好不容易遇到一个注释清晰的,但是不能实现我想要实现的效果。最后找到了一个可塑性较好的瀑布流代码(代码链接
    我想要的几个特点是:

    1. 最基本的瀑布流效果
    2. 可以有多列,至少要有两列
    3. 每个cell里面的图片可以自适应(这个就是自己写的)

    基本代码如下:

    WCLWaterFallLayout.swift

    
    import UIKit
    
    @objc protocol WCLWaterFallLayoutDelegate {
        //waterFall的列数
        func columnOfWaterFall(_ collectionView: UICollectionView) -> Int
        //每个item的高度
        func waterFall(_ collectionView: UICollectionView, layout waterFallLayout: WCLWaterFallLayout, heightForItemAt indexPath: IndexPath) -> CGFloat
    }
    
    
    class WCLWaterFallLayout: UICollectionViewLayout {
        //代理
        weak var delegate: WCLWaterFallLayoutDelegate?
        //行间距
        @IBInspectable var lineSpacing: CGFloat   = 20
        //列间距
        @IBInspectable var columnSpacing: CGFloat = 20
        //section的top
        @IBInspectable var sectionTop: CGFloat    = 0 {
            willSet {
                sectionInsets.top = newValue
            }
        }
        //section的Bottom
        @IBInspectable var sectionBottom: CGFloat  = 0 {
            willSet {
                sectionInsets.bottom = newValue
            }
        }
        //section的left
        @IBInspectable var sectionLeft: CGFloat   = 0 {
            willSet {
                sectionInsets.left = newValue
            }
        }
        //section的right
        @IBInspectable var sectionRight: CGFloat  = 0 {
            willSet {
                sectionInsets.right = newValue
            }
        }
        //section的Insets
        @IBInspectable var sectionInsets: UIEdgeInsets      = UIEdgeInsets.zero
        //每行对应的高度
        private var columnHeights: [Int: CGFloat]                  = [Int: CGFloat]()
        private var attributes: [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
        
        //MARK: Initial Methods
        init(lineSpacing: CGFloat, columnSpacing: CGFloat, sectionInsets: UIEdgeInsets) {
            super.init()
            self.lineSpacing      = lineSpacing
            self.columnSpacing    = columnSpacing
            self.sectionInsets    = sectionInsets
        }
        
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
        
        //MARK: Public Methods
        
        
        //MARK: Override
        override var collectionViewContentSize: CGSize {
            var maxHeight: CGFloat = 0
            for height in columnHeights.values {
                if height > maxHeight {
                    maxHeight = height
                }
            }
            return CGSize.init(width: collectionView?.frame.width ?? 0, height: maxHeight + sectionInsets.bottom)
        }
        
        override func prepare() {
            super.prepare()
            guard collectionView != nil else {
                return
            }
            if let columnCount = delegate?.columnOfWaterFall(collectionView!) {
                for i in 0..<columnCount {
                    columnHeights[i] = sectionInsets.top
                }
            }
            let itemCount = collectionView!.numberOfItems(inSection: 0)
            attributes.removeAll()
            for i in 0..<itemCount {
                if let att = layoutAttributesForItem(at: IndexPath.init(row: i, section: 0)) {
                    attributes.append(att)
                }
            }
        }
        
        override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            if let collectionView = collectionView {
                //根据indexPath获取item的attributes
                let att = UICollectionViewLayoutAttributes.init(forCellWith: indexPath)
                //获取collectionView的宽度
                let width = collectionView.frame.width
                if let columnCount = delegate?.columnOfWaterFall(collectionView) {
                    guard columnCount > 0 else {
                        return nil
                    }
                    //item的宽度 = (collectionView的宽度 - 内边距与列间距) / 列数
                    let totalWidth  = (width - sectionInsets.left - sectionInsets.right - (CGFloat(columnCount) - 1) * columnSpacing)
                    let itemWidth   = totalWidth / CGFloat(columnCount)
                    //获取item的高度,由外界计算得到
                    let itemHeight  = delegate?.waterFall(collectionView, layout: self, heightForItemAt: indexPath) ?? 0
                    //找出最短的那一列
                    var minIndex = 0
                    for column in columnHeights {
                        if column.value < columnHeights[minIndex] ?? 0 {
                            minIndex = column.key
                        }
                    }
                    //根据最短列的列数计算item的x值
                    let itemX  = sectionInsets.left + (columnSpacing + itemWidth) * CGFloat(minIndex)
                    //item的y值 = 最短列的最大y值 + 行间距
                    let itemY  = (columnHeights[minIndex] ?? 0) + lineSpacing
                    //设置attributes的frame
                    att.frame  = CGRect.init(x: itemX, y: itemY, width: itemWidth, height: itemHeight)
                    //更新字典中的最大y值
                    columnHeights[minIndex] = att.frame.maxY
                }
                return att
            }
            return nil
        }
        
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            return attributes
        }
    }
    
    

    代码流畅,注释清晰
    接着就是应用部分主要是以下部分代码

     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            imageindex =  indexPath.row
        }
        
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            if miaoshu.count > imagenames.count
            {
                return imagenames.count
            }
            else
            {
                //return (miaoshu1?.count)!
                return miaoshu.count
            }
        }
        
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Identifier", for: indexPath)
            let color = UIColor.init(red: 255.0/255.0, green: 204.0/255.0, blue: 204.0/255.0, alpha: 0.5) 
            cell.contentView.backgroundColor = color
    
            //let imagename = "p"+String(indexPath.row % 6+1)
           // imagename =  String(indexPath.row % 11+1)
            if imageget != nil && indexPath.row == 0
            {
                image = imageget
            }
            else
            {
                
                imagename = imagenames[indexPath.row ]
                image = UIImage(named: imagename)
            }
            let imageheight = image?.size.height
            let imagewidth = image?.size.width
            let rate = imagewidth! / imageheight!
            let height = self.collectionView.bounds.width / rate
            
            
            
            let imageView = UIImageView(frame: CGRect(x:0, y: 1, width: self.collectionView.bounds.width/2-5, height: (height)/2))
            imageView.image = image
            imageView.layer.cornerRadius = 10
            imageView.layer.masksToBounds = true
            cell.contentView.addSubview(imageView)
            
           
            
            let labelName = UILabel(frame: CGRect(x: 0,y:height/2 + 10 , width: self.collectionView.bounds.width/2-5, height: 20))
            if miaoshuget != "" && indexPath.row == 0
            {
                labelName.text = self.miaoshuget
            }
            else
            {
                labelName.text = miaoshu[indexPath.row ]
            }
            labelName.textAlignment = .center
            labelName.font = UIFont.systemFont(ofSize: 20)
            cell.contentView.addSubview(labelName)
            
            cell.contentView.clipsToBounds      = true
            cell.contentView.layer.cornerRadius = 8
           
            return cell
            
        }
        
        func columnOfWaterFall(_ collectionView: UICollectionView) -> Int {
            return columnCount
        }
        
        func waterFall(_ collectionView: UICollectionView, layout waterFallLayout: WCLWaterFallLayout, heightForItemAt indexPath: IndexPath) -> CGFloat {
            //image = UIImage(named: String(indexPath.row % 11+1))
            if imageget != nil && indexPath.row == 0
            {
                image = imageget
            }
            else
            {
                
                image = UIImage(named: imagenames[indexPath.row ])
            }
            let imageheight = image?.size.height
            let imagewidth = image?.size.width
            let rate = imagewidth! / imageheight!
            let height = (self.collectionView.bounds.width / rate ) / 2 + 40
    
            return CGFloat(height)
        }
    

    关于图片自适应的思路:首先以两列的瀑布流来看,由于列数固定,那么每个cell的宽width应该是一样的,要想每个cell里面的图片不失真(压缩或者拉伸),应该根据图片的的宽和高的比例来对应设置每个cell的高hight,于是得到一个表达式:cell_hight/cell_width=image_hight/image_wight,通过以上表达式就可以完成图片自适应的效果

    展开全文
  • html5实现瀑布流效果

    千次阅读 2017-01-07 13:56:33
    html5实现瀑布流效果

           先给出极客学院的一个瀑布流小例程:瀑布流demo。这是个实现瀑布流很典型的demo。这个例子的实现思路是这样的:父级元素container采用相对定位,子元素container使用绝对定位,用函数imgLocation()计算位置坐标的,有兴趣的童鞋可以参考。

           刚好我要做个整脏治乱曝光台的的项目,需要用到瀑布流的效果,也就参照了这个例子。下面记录下我做这个项目时碰到的问题。项目地址:整脏治乱曝光台

    1.图片重叠的问题

           当我参照上述的demo实现瀑布流时,发现多张图片叠加在一起。后来分析发现是由于图片尚未完全加载到DOM,js就执行了高度计算函数,导致图片叠加在一起,为了解决这个问题,就需要在js中判断上一张图片是否已经加载完成,只有上一张图片加载完成,再加载下一张图片。代码如下:

    $(loadingImgId).load(function(){                            // 只有当前图片加载完后,才能计算坐标,否则图片会重叠在一起
                refreshBoxHeightArr(BoxHeightArr, (currentPage - 1)*10 + index);
                $("#players")[0].style.height = Math.max.apply(null, BoxHeightArr) + "px";  // 为了列表元素和加载提示不重合,需要实时更新players的高度
                if (index == (playerList.length - 1)){
                    index++;
                }
                else if (index < (playerList.length - 1)){
                    index++;
                    addList(playerList, index, BoxHeightArr, currentPage);   // 自调用,加载完一张图片后,再加载下一张图片,防止图片重叠
                }
            });


    2.如何实现两列瀑布流?

    两列瀑布流的效果如下图所示:


    html是用js动态加载的,代码如下:

    <span style="white-space:pre">	</span>template =  '<div class="listBox">';
            template += '   <div class="innerBox1">';
            template += '       <div class="innerBox2">';
            template += '           <a href="/wishDriftBottle/html5/detailedWish.html?id={id}">';       // 在detailedWish.html通过id获取心愿信息
            template += '               <div class="idAndName">';
            template += '                   <img class="officialPic officialPic{wishNo}" style="display: none;" src="/wishDriftBottle/imgs/sourceImgs/official.png">';
            template += '                   <span class="idSpan">{wishNo}号 {fullname}</span>';
            template += '                   <img class="status publishing{wishNo}" style="display: none;" src="/wishDriftBottle/imgs/sourceImgs/publishing.png">';
            template += '                   <img class="status finished{wishNo}" style="display: none;" src="/wishDriftBottle/imgs/sourceImgs/finished.png">';
            template += '               </div>';
            template += '               <div class="imgAndContent imgAndContent{wishNo}"> </div>';
            template += '               <div class="vote">';
            template += '                   <span class="helpText">已获得{votesNum}人帮助</span>';
            template += '               </div>';
            template += '           </a>';
            template += '       </div>';
            template += '   </div>';
            template += '</div>';


    CSS代码如下:

    .listBox {
        float: left;
        width: 50%;
        -webkit-transform: translate3d(0,0,0);
    }
    
    .innerBox1{
        padding: 5px;
    }
    
    .innerBox2 {
        border: 5px solid #ffffff;
        border-radius: 5px;
    }
    
    .wishImg, .helpImg{
        width: 100%;
    }

           按照上述动态加载页面的js代码和CSS样式,就可以实现了。

    3.分页之间图片重叠在一起?

              这个问题,请参照我另外一篇博文:html5上划实现分页加载

    4.初始打开页面,多张图片叠在一张图片上,然后展开。给用户感觉闪烁。原因及解决方法。

          经分析,发现是由于将当前图片加载到DOM时,没有立即给这张图片计算绝对定位的坐标,而是采用默认的"float:left;"方式,这样,从第三张图片开始,初始加载时都会显示在一个地方,直到js执行到函数elementLocation(),图片才会显示在正确的位置,因此需要在图片加载到DOM后立即计算当前图片的坐标,这张图片加载完后,再更新瀑布流两列元素的总高度。js代码如下所示。

    /**
     * 添加列表,瀑布流效果,仅支持有图片显示
     * @param BoxHeightArr 瀑布流左右两列的总高度数组
     */
    function addList(playerList, index, BoxHeightArr, currentPage){
        var template = "";
        var html = "";
        if (index < playerList.length){
            template =  '<div class="listBox">';
            template += '   <div class="innerBox1">';
            template += '       <div class="innerBox2">';
            template += '           <a href="/exposure/html5/detailedPage.html?id={id}?ver=0.0.3">';       // 在detailedWish.html通过id获取心愿信息
            template += '               <div class="placeDiv">地点:<span class="place">{place}</span></div>';
            template += '               <div class="imgAndContent imgAndContent{number}">';
            template += '                   <img class="exposureImg" id="exposureImg{number}">';     // 将img元素插入imgAndContent
            template += '                   <div class="shade_1">';
            template += '                       <span class="idSpan">{number}号 {creatorNickname}</span>';
            template += '                   </div>';
            template += '               </div>';
            template += '               <div class="supportAndCreateTime">';
            template += '                   <div>已获得<span class="helpText">{likeCount}</span>人支持</div>';
            template += '                   <span class="createTime">{createTime}</span>';
            template += '               </div>';
            template += '           </a>';
            template += '       </div>';
            template += '   </div>';
            template += '</div>';
    
            var number = parseInt(playerList[index].number);
            playerList[index].number = number;
    
            var timestamp = playerList[index].createTime;           // 时间戳设置为北京时间
            playerList[index].createTime = formatDate(timestamp);
    
            html = template.formatString(playerList[index]);
            $(".players").append(html);
            boxLocation(BoxHeightArr, (currentPage - 1)*10 + index);           // 计算当前列表元素的坐标(绝对定位)
            $("#players")[0].style.height = Math.max.apply(null, BoxHeightArr) + "px";  // 为了列表元素和加载提示不重合,需要实时更新players的高度
    
            var wish = playerList[index];
            var wishImgUrls = wish.urls;
    
            var url = wishImgUrls[0];
            var loadingImgId = "#exposureImg" + number;
            $(loadingImgId).attr('src', imagesPrefix + url + "?imageView2/2/w/300");     // 加载宽度裁剪到300px的图片
            $(loadingImgId).load(function(){                            // 当前图片加载完后,更新BoxHeightArr[]
                refreshBoxHeightArr(BoxHeightArr, (currentPage - 1)*10 + index);
                $("#players")[0].style.height = Math.max.apply(null, BoxHeightArr) + "px";  // 为了列表元素和加载提示不重合,需要实时更新players的高度
                if (index == (playerList.length - 1)){
                    index++;
                }
                else if (index < (playerList.length - 1)){
                    index++;
                    addList(playerList, index, BoxHeightArr, currentPage);   // 自调用,加载完一张图片后,再加载下一张图片,防止图片重叠
                }
            });
        }
    }

    6.页面中有几十张图片以上时,加快页面加载速度的方法

    待补充

    7.players添加样式overflow:auto;的问题

    待补充


    展开全文
  • html中的瀑布流是什么

    千次阅读 2019-01-07 10:22:03
    html中的瀑布流是什么 ...3、瀑布流使用前置性条件:瀑布流很多有特定的使用前置性条件,不要乱用   二、瀑布流应用场景 首先,我们得明确一点,瀑布流肯定是有好处的,不然pinterest不可能那么火,...
  • 瀑布流

    2018-12-18 15:41:39
    public class PubuliuActivity extends AppCompatActivity { private RecyclerView recy; private ArrayList&lt;BeaytyBean&gt; list=new ArrayList&lt;&... private int[] mImages={R.drawable.dd,R....
  • 手机版瀑布流

    2020-07-29 14:20:30
    手机版瀑布流,兼容所有的手机,手机版爆布流,最好用的爆布流,两列瀑布流
  • 1、waterfall-Jquery瀑布流插件,Jquery瀑流式插件 瀑布流布局在目前貌似很火爆,因为自己用jquery比较多,便萌生了把瀑布流做成插件的想法,图片就借用迅雷UED上的那些美图吧。 2、基于JQuery的自动下拉滚动式...
  • 瀑布流布局的原理及实现

    万次阅读 2017-01-13 19:47:54
    瀑布流很漂亮~但其实实现起来很简单,让我们来实现一下吧瀑布流布局的原理 瀑布流布局要求要进行布置的元素等宽,然后计算元素的宽度与浏览器宽度之比,得到需要布置的列数。 创建一个数组,长度为列数,里面的值为...
  • 瀑布流布局实现的三种方式

    万次阅读 2018-06-05 20:30:29
    瀑布流布局的特点? 答:首先,是图片的宽度固定,图片的长度不一样。其次,是当页面滚动时 ,会再次加载数据,动态的渲染在页面上。瀑布流布局的原理? 首先,获取图片的固定的宽度W,网页body的clientWidth ...
  • 很简单的Vue.js瀑布流布局

    千次阅读 2017-08-04 16:53:41
    实现瀑布流布局也很简单。 将页面分为N列。(可以用flex布局) 需要渲染的数据列表在filters里预处理。新建一个N项嵌套列表,前N个直接对应放进取,后面的每个放在总高度最小的那一项列表。 分列渲染。
  • 小程序实现瀑布流

    千次阅读 热门讨论 2018-12-12 15:15:58
    先上代码 &lt;view class="list"&gt; &lt;view class='list-half'&gt; &lt;view wx:for="{{listData}}" wx:key="index" wx:if="{{index%2 == 0}}"...l
  • 【css】最简单的瀑布流布局方法

    千次阅读 2018-09-19 17:54:34
    前言:用column-count就能实现简单的瀑布流布局
  • 这个开源库还是挺好用的,...瀑布流当然是图片居多,图片的加载我又用到这个开源库:Android-Universal-Image-Loader ,其实这个开源库可以说的东西也很多,图片加载之利器有木有,不过今天的主角是瀑布流,先来介绍
  • Android使用Recycler View实现瀑布流效果

    万次阅读 2018-07-24 23:22:12
    下图是淘宝上瀑布流的一个应用场景,今天我们就来用Recycler View实现以下瀑布流效果 一:创建Activity activity中 核心代码为 mRvPu.setLayoutManager(new StaggeredGridLayoutManager(2,...
  • RecyclerView实现瀑布流,图片自适应高度

    万次阅读 热门讨论 2016-12-05 17:54:42
    对于RecyclerView,相信大家都不陌生了,这个集listView,GridView,瀑布流效果与一身强大控件,渐渐地渗透在每个App.... 还是回到正题,如何让RecyclerView里的图片自适应高度? 我们知道,要让RecyclerView有瀑布...
  • 两行css如下: ``` &lt;style scoped&gt; .waterfall-container { /*分几列*/ column-count: 2; } .waterfall-item { /*不留白,不知道什么意思可以取消这个样式试试*/ break-inside: avoid;...```...
  • RecyclerView 实现瀑布流的正确姿势

    万次阅读 2018-07-26 21:47:58
    首先来看一下瀑布流效果: 加载的数据根据自己需求自己定义。 来说一下具体实现: private RecyclerView rlv; private FlashApapter mAdapter; //设置layoutManager StaggeredGridLayoutManager manager = ...
  • vue中的瀑布流布局组件 需求:图片容器宽度固定,高度根据图片自适应,图片一行不能排列时候,换行依次从左往右排列。(瀑布流概念) 父组件传递数据: waterfallData:[ { e_img: &amp;quot;test.jpg&amp...
  • Android学习之RecylerView完美实现瀑布流效果

    万次阅读 热门讨论 2016-05-28 15:00:07
    对于RecylerView已经讲解很多了,我们都知道RecylerView包含三种布局管理器,分别是LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager,对应实现单行列表,多行列表,瀑布流式布局。 也分别都...
1 2 3 4 5 ... 20
收藏数 32,030
精华内容 12,812
关键字:

瀑布流