vue.js+element-ui实现菜单移动轮播二


上篇说到,两端元素会出现平行移动,看着不协调,应该是左移时第一个从左移出从右移入,右移时最后一个从右移出从左移入,现在开始优化。

1.我们控制数组移动实际上是再改变数组元素所绑定的下标数组indexList,如何做到第一个数组从左移出再从右移入呢?

我想到一个办法,在原数组末位再添加一个元素,这个元素是原数组的第一个元素,在首位添加一个新元素,这个元素是原素组的最后一个元素;

我们看到的数组不变还是5个,只不过是处理后数组的中间五位,两端被遮盖了。

此时菜单数组有7位,我们修改下styleList数组,在原数组两端添加两个样式

      list: [{ title: "吃饭" }, { title: "睡觉" }, { title: "打游戏" }, { title: "逛街" }, { title: "撩妹" }],
      indexList: [], //下标列表
      centerNum: 0, //中间位置的下标
      theFirstIndex: 0, //存储页面展示的数组中第一位下标
      theLastIndex: 0, //存储页面展示的数组中最后一位下标
      styleList: [
        {
          width: "160px",
          height: "240px",
          top: "210px",
          left: "-240px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "160px",
          height: "240px",
          top: "280px",
          left: "0",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "180px",
          height: "260px",
          top: "350px",
          left: "260px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "34px",
            lineHeight: "34px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "200px",
          height: "280px",
          top: "420px",
          left: "530px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "40px",
            lineHeight: "40px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "180px",
          height: "260px",
          top: "350px",
          left: "820px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "34px",
            lineHeight: "34px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "160px",
          height: "240px",
          top: "280px",
          left: "1100px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "160px",
          height: "240px",
          top: "210px",
          left: "1350px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        }
      ]
data全局变量

2.需要一个方法,初始化数组并且每次移动后都要将数组首尾元素重新赋值

这里有个麻烦的地方,我们在页面上看到的菜单数组顺序是变化的,但是在代码中,数组除了两端,中间部分是不变的,只是每个元素的样式变了,

当点击了一个菜单,indexList数组内元素顺序发生变化后,页面展示的第一位并不是代码中7位数组的第二位,

例如:开始时,第一位的下标时1,我点击了第四个菜单,整体左移了一位,indexList数组整体右移了一位,这时,第一位的下标是2

所以我们需要记录页面展示的数组的第一位的下标,每次菜单整体左移时,++,整体右移时,--

初始化时,它是1,末位是5,

反之,末位下标也要记录

    //初始化菜单数组,在首尾添加新元素
    initList(num) {
      const that = this;
      var start = [];
      var mid = [];
      var end = [];
      var newArray = [];
      if (num == 0) {
        //页面初次加载时执行
        mid = that.list;
        end = mid.slice(0, 1);
        start = mid.slice(mid.length - 1, mid.length);
        newArray = start.concat(mid);
        that.list = newArray.concat(end);
        //记录改变后的数组在页面展示的第一位(取styleList[1]样式)下标 
        值(即indexList.indexOf(1))
        that.theFirstIndex = that.indexList.indexOf(1);
        that.theLastIndex = that.indexList.indexOf(that.list.length - 2);
      } else {
        //移动后执行
        mid = that.list.slice(1, that.list.length - 1);
        end = that.list.slice(that.theFirstIndex, that.theFirstIndex + 1);
        start = that.list.slice(that.theLastIndex, that.theLastIndex + 1);
        var startIndex = 0;
        var endIndex = 0;
        if (that.theFirstIndex <= 0) {
          startIndex = that.indexList.length - 1;
        } else {
          startIndex = that.theFirstIndex - 1;
        }
        if (that.theLastIndex >= that.indexList.length - 1) {
          endIndex = 0;
        } else {
          endIndex = that.theLastIndex + 1;
        }
        that.list[startIndex] = start[0];
        that.list[endIndex] = end[0];
      }
    }
处理数组方法

3.每次移动后都要对两个下表变量处理

    //菜单整体向左移一位,下标数组向右移一位
    moveToRight() {
      this.styleList[0].transition = "none";
      this.styleList[0].textStyle.transition = "none";
      this.styleList[this.styleList.length - 1].transition = "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear";
      this.styleList[this.styleList.length - 1].textStyle.transition = "font-size 0.4s linear, line-height 0.4s linear";
      this.indexList = this.indexList.splice(1, this.indexList.length).concat(this.indexList);
      if (this.theFirstIndex <= 0) {
        this.theFirstIndex = this.indexList.length - 1;
      } else {
        this.theFirstIndex--;
      }
      if (this.theLastIndex <= 0) {
        this.theLastIndex = this.indexList.length - 1;
      } else {
        this.theLastIndex--;
      }
      this.initList(1);
    },
    //菜单 整体向右移一位,下标数组向左移一位
    moveToLeft() {
      this.styleList[this.styleList.length - 1].transition = "none";
      this.styleList[this.styleList.length - 1].textStyle.transition = "none";
      this.styleList[0].transition = "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear";
      this.styleList[0].textStyle.transition = "font-size 0.4s linear, line-height 0.4s linear";
      this.indexList = this.indexList.splice(this.indexList.length - 1, this.indexList.length).concat(this.indexList);
      if (this.theFirstIndex >= this.indexList.length - 1) {
        this.theFirstIndex = 0;
      } else {
        this.theFirstIndex++;
      }
      if (this.theLastIndex >= this.indexList.length - 1) {
        this.theLastIndex = 0;
      } else {
        this.theLastIndex++;
      }
      this.initList(1);
    }
移动方法

 

4.这样的,我们去掉styleList两端元素的transition属性

效果图:

但是这样的话,移出效果没有了,因为它的transition属性没有了,就会导致这个现象,那么我们动态控制它的transition属性,

因为在移出时需要移动效果,我们向左移动时,先把styleList[0]添加transition属性,把styleList[6]去掉transition属性,右移反之,代码见第3点移动方法

5.最后隐藏掉两端就可以了,在盒子样式中添加overflow:hidden;完成!

6.完整代码,有不好的地方还请多多指教!

<template>
  <el-row id="myMenu">
    <el-row class="nav">
      <el-row class="setPosition borderBox" v-for="(item,index) in list" :key="index" :style="styleList[indexList[index]]">
        <span class="titleText" :style="styleList[indexList[index]].textStyle" @click="moveToCenter(indexList[index])">{{item.title}}</span>
        <!-- <br>我取的是indexList[{{index}}]={{indexList[index]}} -->
        <!-- <br>我是页面中展示的第{{indexList[index]}}位 -->
      </el-row>
    </el-row>
  </el-row>
</template>
<script>
export default {
  data() {
    return {
      list: [{ title: "吃饭" }, { title: "睡觉" }, { title: "打游戏" }, { title: "逛街" }, { title: "撩妹" }],
      indexList: [], //下标列表
      centerNum: 0, //中间位置的下标
      theFirstIndex: 0, //存储页面展示的数组中第一位下标
      theLastIndex: 0, //存储页面展示的数组中最后一位下标
      styleList: [
        {
          width: "160px",
          height: "240px",
          top: "210px",
          left: "-240px",
          transition: "none",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "none"
          }
        },
        {
          width: "160px",
          height: "240px",
          top: "280px",
          left: "0",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "180px",
          height: "260px",
          top: "350px",
          left: "260px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "34px",
            lineHeight: "34px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "200px",
          height: "280px",
          top: "420px",
          left: "530px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "40px",
            lineHeight: "40px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "180px",
          height: "260px",
          top: "350px",
          left: "820px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "34px",
            lineHeight: "34px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "160px",
          height: "240px",
          top: "280px",
          left: "1100px",
          transition: "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "font-size 0.4s linear, line-height 0.4s linear"
          }
        },
        {
          width: "160px",
          height: "240px",
          top: "210px",
          left: "1350px",
          transition: "none",
          textStyle: {
            fontSize: "28px",
            lineHeight: "28px",
            transition: "none"
          }
        }
      ]
    };
  },
  created() {
    this.initIndexList(7);
    this.initList(0);
    this.centerNum = 3;
  },
  methods: {
    //初始化下标数组,num为数组长度
    initIndexList(num) {
      this.indexList = [];
      for (var i = 0; i < num; i++) {
        this.indexList[i] = i;
      }
    },
    //初始化菜单数组,在首尾添加新元素
    initList(num) {
      const that = this;
      var start = [];
      var mid = [];
      var end = [];
      var newArray = [];
      if (num == 0) {
        //页面初次加载时执行
        mid = that.list;
        end = mid.slice(0, 1);
        start = mid.slice(mid.length - 1, mid.length);
        newArray = start.concat(mid);
        that.list = newArray.concat(end);
        //记录改变后的数组在页面展示的第一位(取styleList[1]样式)下标值(即indexList.indexOf(1))
        that.theFirstIndex = that.indexList.indexOf(1);
        that.theLastIndex = that.indexList.indexOf(that.list.length - 2);
      } else {
        //移动后执行
        mid = that.list.slice(1, that.list.length - 1);
        end = that.list.slice(that.theFirstIndex, that.theFirstIndex + 1);
        start = that.list.slice(that.theLastIndex, that.theLastIndex + 1);
        var startIndex = 0;
        var endIndex = 0;
        if (that.theFirstIndex <= 0) {
          startIndex = that.indexList.length - 1;
        } else {
          startIndex = that.theFirstIndex - 1;
        }
        if (that.theLastIndex >= that.indexList.length - 1) {
          endIndex = 0;
        } else {
          endIndex = that.theLastIndex + 1;
        }
        that.list[startIndex] = start[0];
        that.list[endIndex] = end[0];
      }
    },
    moveToCenter(index) {
      const that = this;
      var count = this.centerNum;
      if (index > count) {
        that.moveToLeft();
        var interval = setInterval(function() {
          if (index > count + 1) {
            that.moveToLeft();
            count++;
          } else {
            clearInterval(interval);
          }
        }, 4 * 100);
      } else if (index < count) {
        that.moveToRight();
        var interval = setInterval(function() {
          if (index < count - 1) {
            that.moveToRight();
            count--;
          } else {
            clearInterval(interval);
          }
        }, 4 * 100);
      }
    },
    //菜单整体向左移一位,下标数组向右移一位
    moveToRight() {
      this.styleList[0].transition = "none";
      this.styleList[0].textStyle.transition = "none";
      this.styleList[this.styleList.length - 1].transition = "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear";
      this.styleList[this.styleList.length - 1].textStyle.transition = "font-size 0.4s linear, line-height 0.4s linear";
      this.indexList = this.indexList.splice(1, this.indexList.length).concat(this.indexList);
      if (this.theFirstIndex <= 0) {
        this.theFirstIndex = this.indexList.length - 1;
      } else {
        this.theFirstIndex--;
      }
      if (this.theLastIndex <= 0) {
        this.theLastIndex = this.indexList.length - 1;
      } else {
        this.theLastIndex--;
      }
      this.initList(1);
    },
    //菜单 整体向右移一位,下标数组向左移一位
    moveToLeft() {
      this.styleList[this.styleList.length - 1].transition = "none";
      this.styleList[this.styleList.length - 1].textStyle.transition = "none";
      this.styleList[0].transition = "left 0.4s linear, top 0.4s linear, width 0.4s linear,height 0.4s linear";
      this.styleList[0].textStyle.transition = "font-size 0.4s linear, line-height 0.4s linear";
      this.indexList = this.indexList.splice(this.indexList.length - 1, this.indexList.length).concat(this.indexList);
      if (this.theFirstIndex >= this.indexList.length - 1) {
        this.theFirstIndex = 0;
      } else {
        this.theFirstIndex++;
      }
      if (this.theLastIndex >= this.indexList.length - 1) {
        this.theLastIndex = 0;
      } else {
        this.theLastIndex++;
      }
      this.initList(1);
    }
  }
};
</script>
<style scoped>
#myMenu {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
.nav {
  width: 1260px;
  height: 700px;
  margin: 0 auto;
  background: #0157909d;
  overflow: hidden;
}
.setPosition {
  position: absolute;
}
.borderBox {
  border: 1px red solid;
  text-align: center;
}
.titleText {
  font-weight: 400;
  text-align: center;
  font-family: Microsoft YaHei;
  cursor: pointer;
}
</style>
menu.vue

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM