上篇说到,两端元素会出现平行移动,看着不协调,应该是左移时第一个从左移出从右移入,右移时最后一个从右移出从左移入,现在开始优化。
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" } } ]
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>