vuejs實現瀑布流布局(三)


前面寫過vuejs實現的瀑布流布局,《vuejs實現瀑布流布局(一)》和《vuejs實現瀑布流布局(二)》也確實實現了瀑布流布局,但是這個是基於SUI-Mobile實現的無限滾動。

近日稍有空閑,回頭重新實現了一下移動端的瀑布流布局,擺脫了移動端UI框架的束縛。

移動端的適配,采用的是adaptive-version2.js,而無限加載采用的是Vue Scroller。

最終實現的效果大致如下:

 

  解決了無限滾動和移動端適配的問題,瀑布流也就只剩下一個難點,怎么樣讓高度不盡相同的圖片能夠按左右順序排列下來,還不至於錯亂太多,相差太大。

  事實上css也已經為我們提供了解決方案,但是css的方案有一個巨大的缺陷在於:一旦圖片發生變動,不論增加還是減少,或者說圖片資源本身發生變化,他會將整體所有圖片的位置進行重排。就是說只要我們動了任意一張圖片,其布局可能會完全不同。

  而js的瀑布流,主流方案似乎只有兩種(具體更多的方案沒有研究),一個利用絕對定位,一個分左右兩欄(或者多欄),每欄內部垂直布局,而依據圖片高度的不同,將其放入適合的欄目內,實現瀑布流。

  我們這里采用的就是左右兩欄的布局。

<div class="waterfalls">
        <ul>
          <li class="photo" v-for="item in waterfallsLeft" :key="item.id + item.albumId+Math.random()">
            <a href="javascrip:;">
              <img :src="item.src" alt="">
            </a>
            <div class="desc-info">
              <p>編號:<span>{{item.albumId}}</span></p>
            </div>
            <div class="thumbnail">
              <div class="thumbnail-desc">
                <p>{{item.title}}</p>
                <span>{{item.thumbnailUrl}}</span>
              </div>
              <div class="praise active">
                <div>
                  <i>贊</i>
                  <span>{{item.albumId}}</span>
                </div>
              </div>
            </div>
          </li>
        </ul>
        <ul>
          <li class="photo" v-for="item in waterfallsRight" :key="item.id + item.albumId+Math.random()">
            <a href="javascrip:;">
              <img :src="item.src" alt="">
            </a>
            <div class="desc-info">
              <p>編號:<span>00001</span></p>
            </div>
            <div class="thumbnail">
              <div class="thumbnail-desc">
                <p>雙語小學</p>
                <span>詹天佑</span>
              </div>
              <div class="praise active">
                <div>
                  <i>贊</i>
                  <span>92</span>
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>

  div.waterfalls作為外層包裹,而里面的兩個ul,就是兩欄,li就是每一張圖片所對應的數據。ul寬度各占50%,然后浮動。剩下的就是怎么樣讓個張圖片自動歸位,進入waterfallsLeft和waterfallsRight。

  首先請求數據:

  

getData(done){
      let _this = this;
      axios.get("https://jsonplaceholder.typicode.com/photos", {page: this.page})
          .then(res=>res.data)
          .then(res => {
            let counts = res.slice((this.page-1) * this.pageCount, this.page * this.pageCount)
            //  console.log(counts.length)
            counts.forEach(item => {
              item.src ='http://cued.xunlei.com/demos/publ/img/P_'+ this.randomNum()+ '.jpg'
            });
            this.page++;
            this.itemsLen = counts.length;
            this.judgeAllLoaded(counts)
            self.bottom = self.bottom + 10;
            if(done) done();
          })
    },
    randomNum(){  // 三位數隨機數,162以內
      let random = Math.floor(Math.random() * 162)
      return random = random < 10 ? '00'+random : random < 100 ? '0'+random : ''+random;
    },

  請求的是https://jsonplaceholder.typicode.com/photos,有很多數據可以進行一些模擬請求,但是其返回的圖片都是相同大小的,所以為其添加圖片資源,item.src ='http://cued.xunlei.com/demos/publ/img/P_'+ this.randomNum()+ '.jpg'。

  有了數據,就得按照圖片在相同寬度的情況下,高度不同,將其分組分別進入左右兩欄this.judgeAllLoaded(counts)。 

judgeAllLoaded(items){   // 判斷所有圖片是否加載完成
      let _this = this;
      items.forEach(item => {
        let IMG = new Image();
        IMG.src = item.src;
        IMG.width = 100;
        IMG.onload = function () {  
          _this.flag++;
          if(_this.leftHeight <= _this.rightHeight){
            _this.leftHeight += IMG.height;
            _this.waterfallsLeft.push(item)
          }else{
            _this.rightHeight += IMG.height;
            _this.waterfallsRight.push(item)
          }
        }
      })
    }

  這里關鍵點在於:IMG.src = item.src; IMG.width = 100; IMG.onload = function;

  為IMG對象添加src,並設置相同寬度100,然后等待圖片加載完成onload,在圖片加載完成之后,判斷左右兩欄,哪一欄高度較低,該條數據進入哪一欄,這里有一個不大不小的問題,就是由於不確定哪張圖片先加載完成,導致即使請求回來的數據相同,其排列的位置也未必相同,但是已經留下了解決flag作為可能的解決方案。就是每加載完成一張圖片,flag自增,監聽flag的變化,當flag的值與請求回來的數據相等時,再進行數據分配,理論上應該可以解決該問題,留待后面實現。

  數據分配完成,其實瀑布流也已經實現了,剩下的就是無限滾動,繼續分配請求回來的數據了。

  具體代碼可以查看GitHub上的GitProjectWaterfalls

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM