前面写过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

  

 

posted on 2018-07-05 15:32  烛火星光  阅读(6156)  评论(0编辑  收藏  举报