vuejs实现瀑布流布局(三)

前面写过vuejs实现的瀑布流布局,《vuejs实现瀑布流布局(一)》和《vuejs实现瀑布流布局(二)》也确实实现了瀑布流布局,但是这个是基于SUI-Mobile实现的无限滚动。

近日稍有空闲,回头重新实现了一下移动端的瀑布流布局,摆脱了移动端UI框架的束缚。

移动端的适配,采用的是adaptive-version2.js,而无限加载采用的是Vue Scroller。

最终实现的效果大致如下:

vuejs实现瀑布流布局(三)_第1张图片

 

  解决了无限滚动和移动端适配的问题,瀑布流也就只剩下一个难点,怎么样让高度不尽相同的图片能够按左右顺序排列下来,还不至于错乱太多,相差太大。

  事实上css也已经为我们提供了解决方案,但是css的方案有一个巨大的缺陷在于:一旦图片发生变动,不论增加还是减少,或者说图片资源本身发生变化,他会将整体所有图片的位置进行重排。就是说只要我们动了任意一张图片,其布局可能会完全不同。

  而js的瀑布流,主流方案似乎只有两种(具体更多的方案没有研究),一个利用绝对定位,一个分左右两栏(或者多栏),每栏内部垂直布局,而依据图片高度的不同,将其放入适合的栏目内,实现瀑布流。

  我们这里采用的就是左右两栏的布局。

  • 编号:{{item.albumId}}

    {{item.title}}

    {{item.thumbnailUrl}}
    {{item.albumId}}
  • 编号:00001

    双语小学

    詹天佑
    92

  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。

  

 

转载于:https://www.cnblogs.com/zhuhuoxingguang/p/9268587.html

你可能感兴趣的:(vuejs实现瀑布流布局(三))