微信小程序下瀑布流加載解決方案

一、什麼是瀑布流

1.一、瀑布流,又稱瀑布流式佈局。是比較流行的一種網站頁面佈局,圖片的寬度是固定的,高度自動。視覺表現爲良莠不齊的多列布局,隨着頁面滾動條向下滾動,這種佈局還會不斷加載數據塊並附加至當前尾部。css

二、h5下實現一個瀑布流的基本思路

2.一、定義基本的html結構

<div class="container">
     <div class="list">
         <img src="" alt="">
     </div>
     <div class="list">
         <img src="" alt="">
     </div>
</div>

2.二、定義基本的css樣式

.container{
.container{width: 100%;padding: 10px 10px;position: relative;}
.list{float: left;width: 100px;padding: 10px;bottom: 10px;}
.list img{width: 100px;}

2.三、js動態計算加載項的樣式。

function water_fall(parent_selector,box_selector){
    let boxElem=document.getElementsByClassName(box_selector);
    let boxWidth=boxElem[0].offsetWidth;
    let cols=2;
    let height_arr=[];
    for(let i=0;i<boxElem.length;i++){
        let cur_box=boxElem[i];
        let cur_box_height=cur_box.offsetHeight;
        if(i<cols){
            height_arr.push(cur_box_height);
        }else{
            let minH = Math.min.apply(null, height_arr);
            let index=height_arr.indexOf(minH);
            cur_box.style.cssText+=`;position: absolute;top:${minH}px;left:${boxWidth*index}px`;
            height_arr[index]+=cur_box_height;
        }
    }
    var maxH = Math.max.apply(null, height_arr);
    let parentElem=document.getElementById(parent_selector);
    parentElem.style.cssText+=`;height: ${maxH}px`;
}

這裏固定2列,經過定義一個高度數組,而後遍歷區塊,獲取每一個列表項的高度,而後push到數組,從數組中找到最短的高度所在的位置來決定後面的列表加入到哪一列,而且設置它的left和top。到此一個簡單的瀑布流已經完成,上面的代碼其實還能夠優化。每次只需遍歷新加載的數據,而後追加到父節點中。
效果圖以下:html

clipboard.png

或者微信打開:https://wx54540d14c1b298c1.mg...小程序

三、如何在微信小程序下實現一個瀑布流。

說了這麼多,其實無非是想接下來作一個對比,來看下微信小程序下怎麼實現一個瀑布流。
仍是分3步
3.一、定義基本的wxml結構微信小程序

<view class="content_list">
    <view class="list ">
        <image class="img_item " src="xxx"/>
    </view>
     <view class="list ">
        <image class="img_item " src="xxx"/>
    </view>
</view>

3.二、定義基本的wxss樣式數組

.content_list{position: relative;}
.list{width: 350rpx;min-height: 200rpx;}
.img_item{width: 100%;}

這裏有個差異,就是我沒有給.list這個class設置padding了,由於在微信小程序下是不可以操做節點獲取樣式的。
後面咱們將根據圖片的寬度動態計算左右兩邊以及左邊一列圖片的padding。同時這裏圖片的單位用的是rpx。主要是爲了適應不一樣屏幕終端。
3.三、js動態計算加載項的樣式。
兩種方案,第一種定義一個隱藏域,用於存放圖片,當圖片加載的時候綁定加載事件獲取圖片的寬高緩存

<view style="display:none">
        <image  wx:for="{{temImgArr}}" wx:key="id" id="{{item.id}}" binderror="onImageError" src="https:{{item.link}}" bindload="onImageLoad"></image>
    </view>

主要js代碼以下:服務器

onImageLoad: function (e) {
        let imageId = e.currentTarget.id;
        let oImgW = e.detail.width;         //圖片原始寬度
        let oImgH = e.detail.height;        //圖片原始高度
        let imgWidth = (this.data.winWidth - 20) * 0.48;
        let scale = imgWidth / oImgW;        //比例計算
        let imgHeight = scale * oImgH;
        let imgObj = {
            id: imageId,
            width: imgWidth,
            height: imgHeight
        };
        imgLen++;
        for (let i = 0; i < temResImgArr.length; i++) {
            if (temResImgArr[i].id == imageId) {
                temResImgArr[i].width = imgWidth;
                temResImgArr[i].height = imgHeight;
                break;
            }
        }
        if (imgLen == temResImgArr.length) {//圖片遍歷完
            this.waterFall();
        }

    },
    onImageError: function (e) {
        imgLen++;
    },
     waterFall: function () {
        for (let i = 0; i < temResImgArr.length; i++) {
            if (heightArr.length < 2 && i < 2) {
                heightArr.push(temResImgArr[i].height + 10);
            } else {
                let minH = Math.min.apply(null, heightArr);
                let index = heightArr.indexOf(minH);
                temResImgArr[i].top = `${minH}`;
                temResImgArr[i].left = `${360 * index}rpx`;
                heightArr[index] += (temResImgArr[i].height + 10);
            }
        }
        let maxH = Math.max.apply(null, heightArr);
        let temp = this.data.imgArr;
        temp.push(...temResImgArr);
        this.setData({
            imgArr: temp,
            viewHeight: maxH,
            temImgArr: []
        });
        //重置數據。
        temResImgArr = [];
        imgLen = 0;
        wx.hideToast();
    },

可是這種方案並非最優,須要定義2個臨時數組來處理加載的圖片,同時用戶等待的時間太長,必需要等全部圖片加載完後獲取到全部的高度後纔可以展現出來,體驗很很差。
既然花了大部分時間在獲取圖片寬高上面,那麼爲何不可以從接口輸出圖片寬高呢?
因此要麼上傳圖片的時候把寬高錄入db,可是這種並無什麼意義。要麼就是輸出的時候處理,這時想到了PHP有個getimagesize函數(PHP是世界上最好的語言有木有),能夠獲取到圖片的寬高。這樣就不用改db了。
備註:這裏更正下,組內大神一眼就看出輸出時候用getimagesize函數處理存在性能問題,就是高併發的時候、服務器帶寬很容易耗盡,不一樣進程之間拉取一樣圖片還沒法利用緩存。最後仍是改成將圖片寬高存入後臺。
且看改進後的js代碼:微信

onLoad: function () {
        let self = this;
        imgLen = 0;
        heightArr = [];
        wx.getSystemInfo({
            success: function (res) {
                let imgW = Math.floor(350 * (res.windowWidth) / 750);//圖片在當前屏幕尺寸下的實際寬度
                let colW = Math.floor((res.windowWidth - 2 * imgW) / 3);//左右兩邊邊距和圖片邊距的寬度
                self.setData({
                    winWidth: res.windowWidth,
                    winHeight: res.windowHeight,
                    colW: colW,
                });
                self.getImgInfo();
            }
        })
    },
waterFall: function (data) {
        let j = 0;
        for (let i = 0; i < data.length; i++) {//遍歷動態加載的數據
            let imgW = Math.floor(350 * this.data.winWidth / 750);//獲取圖片在當前屏幕下的實際寬度
            data[i].height = Math.floor(imgW * data[i].height / data[i].width);
            if (heightArr.length < 2 && i < 2) {
                heightArr.push(data[i].height + this.data.colW);//實際高度+動態邊距
                data[i].top = `0`;
                data[i].left = i == 0 ? `${imgW * i + this.data.colW}` : `${imgW * i + 2 * this.data.colW}`;
            } else {
                let minH = Math.min.apply(null, heightArr);
                let index = heightArr.indexOf(minH);
                data[i].top = `${minH}`;
                data[i].left = index == 0 ? `${imgW * index + this.data.colW}` : `${imgW * index + 2 * this.data.colW}`;
                heightArr[index] += (data[i].height + this.data.colW);
            }
        }
        let maxH = Math.max.apply(null, heightArr);
        let temp = this.data.imgArr;
        temp.push(...data);//追加到當前圖片列表中
        this.setData({
            imgArr: temp,
            viewHeight: maxH,
        });
        //重置數據。
        temp=null;
        imgLen = 0;
        wx.hideToast();
    },

實際效果以下:併發

clipboard.png

這樣就實現了一個微信小程序下的瀑布流。實際效果能夠打開微信,掃描左邊二維碼,直接體驗。或者微信小程序搜索拍照POSE大全。裏面附不少美圖,各類拍照姿式等你來完善,來補充,歡迎體驗並上傳本身的小姿式。
PS:無雙不成對,一張圖太單調,請允許我再附上最近作的一款美的砍價小程序,美的認證,砍到便可購買。最近天氣熱,有購買家電的朋友能夠掃碼購買。app

圖片描述圖片描述

最後,若是你有更優的解決方案請告訴我,咱們一塊兒探討,歡迎點評!

相關文章
相關標籤/搜索