类百度图片的固定高度横向瀑布流js方法及纯css实现的方法记录

微信图片_20190117105118.png

纯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">
    <title>Document</title>
    <style>
    div{            
            display: flex;/*显示模式设置为弹性盒子*/
            flex-wrap: wrap;/*进行强制换行*/
        }        
        div:after{            
            /*对最后一个伪元素进行最大限度伸缩*/            
            content: ' ';            
            flex-grow: 999999999999999999999999999999999999;        
        }        
        img{             
            height: 200px;/*高度*/            
            width: auto;            
            margin: 2px;            
            flex-grow: 1;/*进行按比例伸缩*/            
            object-fit: cover;/*进行裁切,并且图片按比例缩放*/        
        }</style>
</head>
<body>
    <div>
        <img src="./11a.jpg"/>
        <img src="./bb.jpg"/>
        <img src="./11a.jpg"/>
        <img src="./bb.jpg"/><img src="./11a.jpg"/>
        <img src="./bb.jpg"/><img src="./11a.jpg"/>
        <img src="./bb.jpg"/><img src="./11a.jpg"/>
        <img src="./bb.jpg"/><img src="./11a.jpg"/>
        <img src="./bb.jpg"/>
    <div>
</body>
</html>

js实现代码及思路:


微信图片_20190117142317.png

原理是木桶原理,把图片放进一个div计算当前排的宽度,如果大于的话,把最后一个pop掉,同时layout当前排,循环下去

<!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">
    <title>Document</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            border: 0;
            width: 100%;
        }

        .ct {
            width: 90%;
            margin: 0 auto;
        }

        /* 图片容器 */
        .img-box {
            float: left;
            display: flex;
        }
        .imgSB {
            margin-bottom: 5px;
            overflow: hidden;
        }
        .imgS {
            margin-right: 5px;
            margin-bottom: 5px;
            overflow: hidden;

        }
        .img-row{
            display: flex;
            flex-wrap: wrap;
        }
 .img-row .img-box:last-child{
     flex:1;
 }
        /* 行容器 清楚子元素(图片容器)的浮动*/
        .img-row::after {
            content: "";
            display: block;
            clear: both;
        }
    </style>
</head>

<body>
    <div class="ct"></div>
    <script>
        var allImgUrl = [];
        window.onload = function () {
            let ct = document.querySelector(".ct");
            let barrel = new Barrel(ct, 60, 200); // 100张图片数量, 指定每行的初始行高为100 
        }
        var debounce = function (idle, action) {
            var last
            return function () {
                var ctx = this,
                    args = arguments
                clearTimeout(last)
                last = setTimeout(function () {
                    action.apply(ctx, args)
                }, idle)
            }
        }
        window.onresize = debounce(100, function () {
            let ct = document.querySelector(".ct");
            ct.innerHTML = "";//删除子节点,resize的时候会比较烦,因为要先把之前的图片存好,删除子节点,然后执行重排..
            let barrel = new Barrel(ct, 60, 200, 'resize'); // 100张图片数量, 指定每行的初始行高为100 
        })

        function Barrel(ct, imgNum, height, type = 'new',ww=0) {
            this.ct = ct; // 木桶布局容器的DOM节点
            this.ww = ww;
            this.type = type;
            this.width = parseInt(window.getComputedStyle(ct, null).getPropertyValue("width")) - 20; // 行宽,预防滚动条出现预留20
            console.log(this.width)
            this.rowHeight = height; // 行高
            this.imgArr = []; // 存放每行图片的数组
            this.loadImg(imgNum);

        }
        Barrel.prototype = {
            getImgUrls: function (imgNum) { //模拟后台获取的图片地址
                console.log(this.type)
                if (this.type !== 'resize') {
                    let imgUrls = [];
                    let colorArr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]; // 颜色数组[0-9, A-F],
                    // 该颜色数组生成与源代码稍有不同,在我的GitHub上是用for循环生成的 

                    for (let i = 0; i < imgNum; i++) {
                        let imgWidth = Math.floor(Math.random() * 500 + 500); // 设定宽度500-1000
                        let imgHeight = Math.floor(Math.random() * 300 + 500); // 设定高度为300-800
                        let bgColor = textColor = ""; // 下面使用的是字符串拼接,每次使用都需要重新清空

                        for (let j = 0; j < 6; j++) {
                            bgColor += colorArr[Math.floor(Math.random() * 16)];
                            textColor += colorArr[Math.floor(Math.random() * 16)];
                        }

                        let url = "http://via.placeholder.com/" + imgWidth + "x" + imgHeight + "/" +
                            bgColor + "/" + textColor;
                        imgUrls.push(url);
                    }
                    allImgUrl = imgUrls;
                    return imgUrls;
                } else {
                    // console.log(allImgUrl)
                    return allImgUrl;
                }
            },
            loadImg: function (imgNum) {
                let imgUrlsArr = this.getImgUrls(imgNum);
                let _this = this; // 保存this指针的指向,方便调用属性及方法

                for (let i = 0; i < imgNum; i++) {
                    let newImg = new Image(); // 新建图片对象
                    newImg.src = imgUrlsArr[i]; // 加载图片内容
                    let ww = 0;
                    newImg.onload = function () {
                        // Image对象加载了src后拥有宽高属性, imgInfo存储图片信息
                        let ratio = this.width / this.height;
                        // console.log(ratio)
                        let imgInfo = {
                            target: this, // 用来存放当前目标newImg,方便后续调用
                            height: _this.rowHeight,
                            width: ratio * _this.rowHeight, // 等比例缩放
                            ratio: ratio,
                        };
                        // 把加载完的图片加入渲染队列
                        _this.render(imgInfo,i);
                    }
                }
            },
            render: function (imgInfo,i) {
                this.imgArr.push(imgInfo);                
                // let ww = 0;
                this.ww += imgInfo.width //性能优化,利用总ww来执行直接加
                if (this.ww > this.width) {
                    let lastImg = this.imgArr.pop();
                    this.ww -= lastImg.width;

                    // 利用面积相等原则,来计算新的高度
                    let newHeight = this.width * this.rowHeight / this.ww;
                    let newRatio = this.width/this.ww;
                    this.layout(newHeight,newRatio);
                    // 放置完毕之前的图片之后,清空该图片队列
                    // 并将上一行溢出的图片 作为下一行的第一张
                    this.imgArr = [];
                    this.imgArr.push(lastImg);
                    this.ww = lastImg.width;//重置ww,但是要等于pop掉的那张图的width
                }
                // 定义该行图片宽度之和
                // let wholeWidth = 0;
                // this.imgArr.push(imgInfo);
                // let wholePadding = 0;
                // for (let i = 0; i < this.imgArr.length; i++) {
                //     wholeWidth += this.imgArr[i].width;
                //     wholePadding += 10;
                // }
                // // 如果该行加入的图片宽度大于了该行的宽度 
                // // 就需要弹出最后一张图片,并更改前面的图片大小比例
                // if (wholeWidth > this.width) {
                //     // console.log(this.imgArr)
                //     let lastImg = this.imgArr.pop();
                //     wholeWidth -= lastImg.width;

                //     // 利用面积相等原则,来计算新的高度
                //     let newHeight = this.width * this.rowHeight / wholeWidth;
                //     let newRatio = this.width/wholeWidth;
                //     console.log(newRatio)
                //     this.layout(newHeight,newRatio);
                //     // 放置完毕之前的图片之后,清空该图片队列
                //     // 并将上一行溢出的图片 作为下一行的第一张
                //     this.imgArr = [];
                //     this.imgArr.push(lastImg);
                // }
            },
            layout: function (newHeight,newRatio) {
                // 一次只放一行, 所以只生成一个imgRow
                let imgRow = document.createElement("div"); //可以选择一排排layout
                imgRow.classList.add("img-row");//可以选择一排排layout
                // console.log(this.imgArr)
                // 一行包含若干个图片,所以需要若干个imgBox,并将图片加入其中
                for (let i = 0; i < this.imgArr.length; i++) {
                    let imgBox = document.createElement("div");
                    imgBox.classList.add("img-box");
                    let imgS = document.createElement("div");
                    if (i === this.imgArr.length - 1) {
                        imgS.classList.add("imgSB");
                    } else {
                        imgS.classList.add("imgS");
                    }
                    let img = this.imgArr[i].target;
                    // 改变了高度之后宽度自己会跟着改变
                    // console.log(newRatio,this.imgArr[i].width)
                    img.style.width =parseInt(newRatio*this.imgArr[i].width)-5+'px';// 注意加"px",减掉一个margin-right的值
                    // img.style.height = newHeight - 5 + "px"; // 注意加"px",减掉一个margin-right的值
                    imgS.appendChild(img);
                    imgBox.appendChild(imgS);
                    imgRow.appendChild(imgBox);
                    // this.ct.appendChild(imgBox);//也可以一个个插入,反正都是float
                }
                // 先把图片加载到图片盒子里,然后加到图片列中,最后加到容器中
                this.ct.appendChild(imgRow);//可以选择一排排layout
            },
        }
    </script>
</body>

</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容

  • 使用纯 CSS 实现 500px 照片列表布局 文章很长,因为介绍了如何一步一步进化到最后接近完美的效果的,不想读...
    HZ充电大喵阅读 2,592评论 0 4
  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,566评论 0 7
  • 请参看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon阅读 7,082评论 2 19
  • 风吹城门临汉渺,一江汉水万古遥。 群侠聚义剑气豪,英雄堆里傲藏骄。 纵是芙蓉花开今又潇, 回眸襄阳一笑牧神雕。 靖...
    十月十日记阅读 377评论 0 6
  • fdlso阅读 148评论 0 0