vue - 中级无限滚动 alloytouch

2022-04-17  本文已影响0人  Petricor
问题

在上一篇文章初级无限滚动我们介绍了无限滚动的思路方法,但是有个明显的问题,当我快速上滑的时候是没有实现惯性的效果。

无惯性效果

方案

所以针对改问题我们可以自己写一个js来控制它的滚动,但是没有这个必要,因为有现成的库已经帮我们做了这件事情了,他就是alloytouch.js alloytouch npm官网地址
ps:因为某家node - v 是v8.11.2 而它最低版本支持是 v10.13.0 ,所以我只能被迫下载使用了

前提概要

1.既然要做无限滚动,所以背景图片的大小应该是已知的,所以本demo就设置成已知 1762px

以下是源码
<template>
  <div class="intermediate-view">
    <div class="lvl-bg"></div>
    <div  class="content"  :class="isLayoutH && 'layout-h'"  id="content"  ref="content"
        :style="isLayoutH && { width: pageW + 'px' }" >
      <div    v-for="(page, pIdx) in pages"   :key="pIdx"    :style="{ top: page.y + 'px'}"
        :class="['group', 'L', { 'snd-page': page.isLast }]" ></div>
    </div>
  </div>
</template>

<script>
import Touch from "../../../utils/touch.js";
export default {
  data() {
    return {
      pageW: 0,
      screenH: 0,
      isLayoutH: false,
      bgImgsH: 1762,
      pages: [
        {
          y: 0,
        },
        {
          y: 0,
        },
      ],
      scrollPosition: { x: 0, y: 0 },
      bgH: null,
      stepTapLock: false,
    };
  },
  mounted() {
    let _sw = window.innerWidth;
    let _sh = window.innerHeight;
    if (_sw > _sh) {
      _sw = Math.ceil(_sh * 0.9);
      this.isLayoutH = true;
    }
    this.pageW = _sw;
    this.screenH = _sh;

    this.bgImgsH = this.getRatioVal(this.bgImgsH);
    this.bgH = this.bgImgsH;

    this.pages[1].y = -1 * this.bgH;
    document.body.addEventListener("touchmove", this.touchmoveEvt, {
      passive: false,
    });
    this.initAlloytouch();
  },
  methods: {
    getRatioVal(val) {
      // 保留一位小数点
      const ratio = this.pageW / 750;
      return Math.ceil(val * 10 * ratio) / 10;
    },
    touchmoveEvt(evt) {
      evt.preventDefault();
    },
    initAlloytouch() {
      let pageMin = this.getRatioVal(-100000);
      let pageMax = this.getRatioVal(100000);

      this.scrollTouch = new Touch({
        touch: "#content",
        target: this.scrollPosition,
        property: "y",
        factor: 1,
        moveFactor: 1,
        preventDefault: false,
        bindSelf: false,
        max: pageMax,
        min: pageMin,
        change: () => {
          this.updatePageRender();
        },
        touchMove: () => {
          this.stepTapLock = true;
        },
        touchEnd: () => {
          this.stepTapLock = false;
        },
      });
    },
    updatePageRender() {
      this.updatePagePositon();
    },
    updatePagePositon() {
      let p = this.scrollPosition.y;
      let h = this.bgH;
      let offset = p % h;
      let v = Math.floor(Math.abs(p) / h) % 2;
      this.pages.forEach((item, i) => {
        let m = 1;
        if (p < 0) {
          m = -1;
        }
        item.y = offset + (i + v - 1) * h * (-2 * v + 1) * m;
      });
      if (this.pages[0].y < this.pages[1].y) {
        this.pages[0].isLast = true;
        this.pages[1].isLast = false;
      } else if (this.pages[1].y < this.pages[0].y) {
        this.pages[0].isLast = false;
        this.pages[1].isLast = true;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.intermediate-view {
  width: 100%;
  height: 100%;
  position: relative;
  background-color: #1990fe;
  overflow: hidden;
  .lvl-bg {
    position: absolute;
    width: 100%;
    height: 100%;
    background-size: 100%;
    filter: blur(20px);
    background-image: url("../../../assets/step-bg2.png");
  }
  .content {
    width: 100%;
    height: 100%;
    position: relative;
    margin: 0 auto;
    &.layout-h {
      box-shadow: 2px -2px 4px 0px rgba(51, 51, 51, 0.2);
    }
  }
  .group {
    position: absolute;
    left: 0;
    width: 100%;
    background-size: 100%;
    &.L {
      height: 1762px;
      background-image: url("../../../assets/step-bg2.png");
    }
    &.snd-page {
      // 解决page间不吻合的问题(缝隙)
      transform: translateY(3px);
    }
  }
}
</style>
效果如下
当为竖屏时候 当为横屏的时候
附录:

如果这篇不清楚的话可以看看上一期内容:

vue 初级无限滚动
alloytouch.js 在 码云 vue-question 项目中

另外附录两个 alloytouch源码解析地址 :

AlloyTouch.js 源码 学习笔记及原理说明
AlloyTouch.js 源码 学习笔记及原理说明
上一篇 下一篇

猜你喜欢

热点阅读