zoukankan      html  css  js  c++  java
  • 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

      

  • 相关阅读:
    python 获取当前路径
    python 执行结果输出为txt
    python def 定义函数
    python:浅析python 中__name__ = ‘__main__’ 的作用
    python 数组新增或删除元素
    python在Windows安装PIL的方法
    静态路由学习总结
    zookeeper客户端命令行操作
    kudu安装过程中可能出现的问题
    sudo: /etc/sudoers is world writable|给用户添加权限报错
  • 原文地址:https://www.cnblogs.com/zhuhuoxingguang/p/9268587.html
Copyright © 2011-2022 走看看