類百度圖片的固定高度橫向瀑布流js方法及純css實現(xiàn)的方法記錄

微信圖片_20190117105118.png

純css實現(xiàn)代碼:

<!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;/*顯示模式設(shè)置為彈性盒子*/
            flex-wrap: wrap;/*進(jìn)行強制換行*/
        }        
        div:after{            
            /*對最后一個偽元素進(jìn)行最大限度伸縮*/            
            content: ' ';            
            flex-grow: 999999999999999999999999999999999999;        
        }        
        img{             
            height: 200px;/*高度*/            
            width: auto;            
            margin: 2px;            
            flex-grow: 1;/*進(jìn)行按比例伸縮*/            
            object-fit: cover;/*進(jìn)行裁切,并且圖片按比例縮放*/        
        }</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實現(xiàn)代碼及思路:


微信圖片_20190117142317.png

原理是木桶原理,把圖片放進(jìn)一個div計算當(dāng)前排的寬度,如果大于的話,把最后一個pop掉,同時layout當(dāng)前排,循環(huán)下去

<!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張圖片數(shù)量, 指定每行的初始行高為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 = "";//刪除子節(jié)點,resize的時候會比較煩,因為要先把之前的圖片存好,刪除子節(jié)點,然后執(zhí)行重排..
            let barrel = new Barrel(ct, 60, 200, 'resize'); // 100張圖片數(shù)量, 指定每行的初始行高為100 
        })

        function Barrel(ct, imgNum, height, type = 'new',ww=0) {
            this.ct = ct; // 木桶布局容器的DOM節(jié)點
            this.ww = ww;
            this.type = type;
            this.width = parseInt(window.getComputedStyle(ct, null).getPropertyValue("width")) - 20; // 行寬,預(yù)防滾動條出現(xiàn)預(yù)留20
            console.log(this.width)
            this.rowHeight = height; // 行高
            this.imgArr = []; // 存放每行圖片的數(shù)組
            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"]; // 顏色數(shù)組[0-9, A-F],
                    // 該顏色數(shù)組生成與源代碼稍有不同,在我的GitHub上是用for循環(huán)生成的 

                    for (let i = 0; i < imgNum; i++) {
                        let imgWidth = Math.floor(Math.random() * 500 + 500); // 設(shè)定寬度500-1000
                        let imgHeight = Math.floor(Math.random() * 300 + 500); // 設(shè)定高度為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指針的指向,方便調(diào)用屬性及方法

                for (let i = 0; i < imgNum; i++) {
                    let newImg = new Image(); // 新建圖片對象
                    newImg.src = imgUrlsArr[i]; // 加載圖片內(nèi)容
                    let ww = 0;
                    newImg.onload = function () {
                        // Image對象加載了src后擁有寬高屬性, imgInfo存儲圖片信息
                        let ratio = this.width / this.height;
                        // console.log(ratio)
                        let imgInfo = {
                            target: this, // 用來存放當(dāng)前目標(biāo)newImg,方便后續(xù)調(diào)用
                            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 //性能優(yōu)化,利用總ww來執(zhí)行直接加
                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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 使用純 CSS 實現(xiàn) 500px 照片列表布局 文章很長,因為介紹了如何一步一步進(jìn)化到最后接近完美的效果的,不想讀...
    HZ充電大喵閱讀 2,779評論 0 4
  • 前端開發(fā)面試題 面試題目: 根據(jù)你的等級和職位的變化,入門級到專家級,廣度和深度都會有所增加。 題目類型: 理論知...
    怡寶丶閱讀 2,682評論 0 7
  • 請參看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon閱讀 7,762評論 2 19
  • 風(fēng)吹城門臨漢渺,一江漢水萬古遙。 群俠聚義劍氣豪,英雄堆里傲藏驕。 縱是芙蓉花開今又瀟, 回眸襄陽一笑牧神雕。 靖...
    十月十日記閱讀 446評論 0 6
  • fdlso閱讀 176評論 0 0

友情鏈接更多精彩內(nèi)容