美文网首页
vue - 初级无限滚动

vue - 初级无限滚动

作者: Petricor | 来源:发表于2022-04-15 18:02 被阅读0次

    问题

    之前做过一个关于闯关的项目,一个分类里面都有600个小关卡,用户需要滚动选择关卡,为了能让页面看起来很好看,所以就做了个无限滚动的页面。


    无限滚动

    思路

      1. 无限滚动并不是真的一直在滚动,而是两张或者更多的可以无限链接的图片相互的变换所在的位置。ps:(就像人民币,两张人民币怎么拼接花纹都能对应)
    • 2.人之所以认为你把图片滑动了,并不是它真的动了,它可以是相对于你的手机屏幕移动而已
    • 3.只要在手指滑动的时候记录手指滑动的高度轨迹,然后让图片的定位相对应的滚动即可


      分析图
    由上图可分析:

    两张图片的top值的范围是(bgh , - bgh]

    <template>
        <div class="elementary-view" name="infinte" id="infinte">
          <div   v-for="(page, idx) in pages"   :key="idx"   class="group" 
            :style="{  top: page + 'px' }" >
            <img class="img" :src="stepBg1" />
          </div>
        </div>
    </template>
    
    <script>
    import stepBg1 from "../../../assets/step-bg1.png";
    export default {
      data() {
        return {
          pageW: 0, // 滚动区域宽度
          pageH: 0, // 滚动区域高度
    
          bgImgsW: 0, // 滚动图片的原始宽度 (可以根据图片直接写成定值)
          bgH: null, //比例高度
          pages: [0, 0], //定义两个图片的初始位置
          startY: 0,
          scrollTotal: 0, //滚动的总距离
    
          thinkShow: false,
          stepBg1: stepBg1,
        };
      },
      mounted() {
        // 获取屏幕宽度和高度
        let infinte = document.getElementById("infinte");
        this.pageW = infinte.clientWidth;
        this.pageH = infinte.clientHeight;
    
        // 获取滚动图片的高度
        let bgImg = document.createElement("img");
        bgImg.setAttribute("crossOrigin", "anonymous");
        bgImg.src = stepBg1;
        bgImg.onload = () => {
          this.bgImgsW = bgImg.width;
          this.bgH = this.getRatioVal(bgImg.height); //获取图片相对比例的高度
    
          this.pages[1] = -1 * this.bgH;
          this.$set(this.pages, 1, -1 * this.bgH);
        };
    
        //定义开始的手势
        infinte.addEventListener("touchstart", this.touchstart, {
          passive: false,
        });
       //定义结束的手势
        infinte.addEventListener("touchend", this.touchend, {
          passive: false,
        });
        //定义滚动的手势
        infinte.addEventListener("touchmove", this.touchmoveEvt, {
          passive: false,
        });
      },
      methods: {
        getRatioVal(val) {
          // 保留一位小数点
          const ratio = this.pageW / this.bgImgsW;
          return Math.ceil(val * 10 * ratio) / 10;
        },
        touchstart(evt) {
          this.startY = evt.changedTouches[0].screenY;
          evt.preventDefault();
        },
        touchend(evt) {
          let endY = evt.changedTouches[0].screenY;
          this.scrollTotal = this.scrollTotal + endY - this.startY; //总共滚动的高度
          this.startY = null;
          evt.preventDefault();
        },
        touchmoveEvt(evt) {
          let touchY = evt.changedTouches[0].screenY; //手指现在的位置
          let onceY = touchY - this.startY;
          this.updatePagePositon(onceY);
        },
        updatePagePositon(onceY) {
          let p = this.scrollTotal + onceY;
          let h = this.bgH;
          let offset = p % h; //余下了多少高度(相对滚动距离)
          let v = Math.floor(Math.abs(p) / h) % 2; //先判断滚动的数量是几个bgh,在相对位置不变的情况我们眼前应该是那个组件
          this.pages.forEach((val, i) => {
            let m = p < 0 ? -1 : 1;
            this.$set(this.pages, i, offset + (i - v) * h * (-2 * i + 1));
          });
        },
      },
    };
    </script>
    
    <style lang="scss" scoped>
    .elementary-view {
        width: 100%;
        height: 100%;
        position: relative;
        background-color: #1990fe;
        overflow: hidden;
        &.layout-h {
          box-shadow: 2px -2px 4px 0px rgba(51, 51, 51, 0.2);
        }
        .group {
          position: absolute;
          left: 0;
          width: 100%;
          .img {
            width: 100%;
          }
        }
    }
    </style>
    
    

    方案清晰思路明白,所以一起都变的简单明了,就唯独剩下计算了
    **解析updatePagePositon 方法 **

        updatePagePositon(onceY) {
          let p = this.scrollTotal + onceY;   //获取总共的滚动的距离
          let h = this.bgH;                          // 定义图片高度
          let offset = p % h;                       //余下了多少高度(相对滚动距离)
          let v = Math.floor(Math.abs(p) / h) % 2;      //先判断滚动的数量是几个bgh,在相对位置不变的情况我们眼前应该是那个组件
    

    从上面代码能看出 :
    offset 是 真正滚动需要增加的距离,
    v 值是 0 || 1

    分析图 1

    从上图分析组合这个公式结果是

    offset + (i - v) * h * (-2 * i + 1)
    //但是该结果在offset为正数时候没问题,为负数时有问题
    
    分析图2

    因为从分析图1 的出的结果能看出
    offset + ( - h) === offset + (i - v) * h * (-2 * i + 1)
    所以分析图2 能得出
    offset + h === offset + (i - v) * h * (-2 * i + 1) * (-1)

          this.pages.forEach((val, i) => {
            let m = p < 0 ? -1 : 1;
            this.$set(this.pages, i, offset + (i - v) * h * (-2 * i + 1) * m);
          });
    
        },
    

    代码地址:码云 vue-question 无限滚动 - 初级无限滚动

    下一篇中级无限滚动

    结束 送你们一张循环图

    循环图

    相关文章

      网友评论

          本文标题:vue - 初级无限滚动

          本文链接:https://www.haomeiwen.com/subject/ifzcertx.html