vue不使用其他插件实现新闻app中左右滑动切换tab菜单和div内容的动画效果(移动端)

在这里插入图片描述

实现如图的效果,当前的tab菜单也是左右可滑动的

首先tab的滑动
如图效果在这里插入图片描述

<div id="apps">
        <nav>
          <p
            v-for="(item,$index) in arrs"
            @click="toggle($index)"
            :class="{active:$index==active}"
          >{{item}}</p>
        </nav>
      </div>

在data中的参数,和点击事件,文章结尾有修改后的toggle事件,点击切换内容

data() {
    return {
      active: 0,
      arrs: ["菜单1", "菜单2", "菜单3", "菜单3",'菜单5','菜单6','菜单7']
    };
 },
 methods: {
	toggle(index) {
 	 	this.active = index;
	},

style样式

#apps{ width: 100%; overflow:hidden; } 
#apps nav{ padding: 0 10px; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: middle; -ms-flex-align: middle; align-items: middle; overflow: auto; } 
#apps p{ text-align: center; font-size: 16px; -ms-flex-negative: 0; flex-shrink: 0; padding: 10px; margin: 5px; }
#apps p.active{ color: #ffff00; background-color: #000000; }


这是tab的滑动代码
接下来是,内容页的滑动切换div和tab的动画的实现代码

页面代码如下:

<div
        class="back"
        @touchstart.prevent="touchStart"
        @touchmove.prevent="touchMove"
        @touchend="touchEnd"
        ref="back"
      >
        <div class="back-l" ref="left"></div>
        <div class="back-m" ref="middle"></div>
        <div class="back-r" ref="right"></div>
      </div>

样式:

<style scoped lang="stylus" rel="stylesheet/stylus">
.back {
  position: fixed;
  width: 100%;
  height: 100px;
  white-space: nowrap;

  .back-l {
    position: relative;
    vertical-align: top;
    display: inline-block;
    width: 100%;
    height: 100%;
    background-color: red;
  }
   .back-m {
    position: relative;
    vertical-align: top;
    display: inline-block;
    width: 100%;
    height: 100%;
    background-color: blue;
  }

  .back-r {
    display: inline-block;
    vertical-align: top;
    position: relative;
    width: 100%;
    height: 100%;
    background-color: yellow;
  }
}
</style>

没有安装stylus的使用以下命令安装使用

npm install stylus stylus-loader --save-dev

以下是js代码

js中data参数:

data() {
    return {
      active: 0,
      currentPlay: "red",
      percent: 0,
      arrs: ["red", "blue", "yellow"]
    };
  },

滑动动作开始:

touchStart(e) {
      const touch = e.touches[0];
      this.touch.startX = touch.pageX;
      this.touch.startY = touch.pageY	;
    },

滑动动作:

touchMove(e) {
      const touch = e.touches[0];
      //横向和纵向偏离位置
      const deltaX = touch.pageX - this.touch.startX;
      const deltaY = touch.pageY - this.touch.startY;
      if (Math.abs(deltaY) > Math.abs(deltaX)) {
        return;
      }
      if(this.currentPlay=='red'){
        var left=0;
        var offsetWidth = Math.min(
        0,
        Math.max(-window.innerWidth, left + deltaX)
        );
      }
      else if(this.currentPlay=='blue'){
         var left=-window.innerWidth;
         if(deltaX>0){  //判断动作 是左滑还是右滑
           var offsetWidth = Math.min(
            0,
            Math.max(-window.innerWidth, left + deltaX)
            );
         }else{
           var offsetWidth = Math.min(
              -window.innerWidth,
              Math.max(-window.innerWidth*2, left + deltaX)
            );
         }
      }
      else{
        var left=-window.innerWidth*2;
        var offsetWidth = Math.min(
          -window.innerWidth,
          Math.max(-window.innerWidth*2, left + deltaX)
        );
      }
      //记录滑动的距离占屏幕宽度的百分比,如果滑动太少则不切换
      this.percent = deltaX / window.innerWidth;
      //动画中滑块的移动
      this.$refs.back.style["transform"] = `translate3d(${offsetWidth}px,0,0)`;
      //设置动画时间
      this.$refs.back.style["transitionDuration"] = 10;
      console.log('');
    },

这个方法简单的介绍一下几个参数把,个人的理解修改offsetWidth ,参数的变化就可以在滑动时产生动画效果,
当最左边滑块时(red)
也就是red的时候offsetWidth= Math.min(0, Math.max(-window.innerWidth, left + deltaX));
当前Math.min中的第一个参数是当前滑块div左边的x坐标为0,Math.max中的第一个参数为当前滑块右边的x的坐标,

当滑块在中间时(blue)
判断当前动作时左滑还是右滑,当左滑时 左边模块为red所以
offsetWidth=Math.min(0, Math.max(-window.innerWidth, left + deltaX));
右滑是为yellow
var offsetWidth = Math.min(-window.innerWidth,Math.max(-window.innerWidth2, left + deltaX));
当前Math.min中的第一个参数是当前滑块div左边的x坐标为-window.innerWidth,Math.max中的第一个参数为当前滑块右边的x的坐标
当滑块在中间时(yellow)
也就是yellow的时候var offsetWidth = Math.min( -window.innerWidth,Math.max(-window.innerWidth
2, left + deltaX));
当前Math.min中的第一个参数是左边滑块div左边的x坐标为0,Math.max中的第一个参数为左边滑块右边的x的坐标

滑动结束的js:

touchEnd() {
      let offsetWidth;
      let percent;
      //当前为红色,滑动占比小于-0.1则切换,否则回到原位置
      if (this.currentPlay === "red") {
        if (this.percent < -0.1) {
          this.currentPlay = "blue";
          this.active=1;
          offsetWidth = -window.innerWidth;
        } else {
          offsetWidth = 0;
        }
      }else if(this.currentPlay === "blue"){
        if (this.percent > 0.1) {
          this.active=0;
          this.currentPlay = "red";
          offsetWidth = 0;
        }
        else if (this.percent < -0.1) {
          this.currentPlay = "yellow";
          this.active=2;
          offsetWidth = -window.innerWidth*2;
        }
        else {
          offsetWidth = -window.innerWidth;
        }
      }
       else {
        //当前为黄色,滑动占比大于0.9则切换,否则回到原位置
        if (this.percent > 0.1) {
          this.currentPlay = "blue";
          this.active=1;
          offsetWidth = -window.innerWidth;
        } else {
          offsetWidth = -window.innerWidth*2;
        }
      }
      //这里的transform是针对最开始的位置而言,而不是移动过程中的位置
      this.$refs.back.style["transform"] = `translate3d(${offsetWidth}px,0,0)`;
      this.$refs.back.style["transitionDuration"] = 10;
    }


补上一个点击tab是切换内容
修改js中的toggle方法,修改成这样,就能同时满足点击切换或者滑动切换

toggle(index) {
      this.active = index;
      if(index==0){
        var offsetWidth = 0;
        this.currentPlay = "red";
      }
      else if(index==1){
        var offsetWidth = -window.innerWidth;
        this.currentPlay = "blue";
      }
      else if(index==2){
        this.currentPlay = "yellow";
        var offsetWidth = -window.innerWidth*2;
      }
      //这里的transform是针对最开始的位置而言,而不是移动过程中的位置
      this.$refs.back.style["transform"] = `translate3d(${offsetWidth}px,0,0)`;
    },

以上就是实现的全部代码,参考与 https://blog.csdn.net/tjzc1352640/article/details/79381155https://blog.csdn.net/jinyuyang78/article/details/78958527 。 在这两个基础上做了自己的理解和改动,如果需要多个tab菜单和页面添加修改 touchMove 和 touchEnd 中的两个判断中的内容即可。