实现弧形轮播图,无论多少数据,都在固定的几个元素上切换,不影响渲染性能
只考虑数据在六个以上,六个以下的需要自己考虑。
<template>
<div class="venue-wrap">
<div class="nav-wrap">
<span
class="prev"
@click="prevItem"
></span>
<span
class="next"
@click="nextItem"
></span>
<ul
class="nav-list"
ref="nav"
>
<li
v-for="(item, index) in showData"
:key="index"
class="item"
:class="'item'+index"
>
{{showData[index].name}}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
components: {
},
props: {
},
data () {
return {
navList: [
{
name: '场馆1',
id: 1
},
{
name: '场馆2',
id: 2
},
{
name: '场馆3',
id: 3
},
{
name: '场馆4',
id: 4
},
{
name: '场馆5',
id: 5
},
{
name: '场馆6',
id: 6
},
{
name: '场馆7',
id: 7
},
{
name: '场馆8',
id: 8
},
{
name: '场馆9',
id: 9
},
{
name: '场馆10',
id: 10
}
],
showData: [],
positionArr: [],
itemArr: [],
num: 0,
preActive: 6,
nextActive: 0
};
},
computed: {
},
created () {
},
mounted () {
this.nextActive = this.navList.length;
// this.navList = [...this.navList, ...this.navList];
this.showData = Array.from(this.navList.filter((item, index) => {
if (index < 6) {
return item;
}
}));
this.$nextTick(() => {
this.init();
});
},
watch: {
},
methods: {
init () {
this.positionArr = [];
let oPic = this.$refs.nav;
this.itemArr = oPic.getElementsByTagName('li');
for (let i = 0; i < this.itemArr.length; i++) {
this.positionArr.push([
parseInt(this.getStyle(this.itemArr[i], 'left')),
parseInt(this.getStyle(this.itemArr[i], 'top')),
parseFloat(this.getStyle(this.itemArr[i], 'opacity')),
this.itemArr[i].offsetWidth
]);
}
},
getStyle (obj, name) {
if (obj.currentStyle) {
return obj.currentStyle[name];
} else {
return getComputedStyle(obj, false)[name];
}
},
prevItem () {
if (this.num === this.showData.length) {
this.num = 0;
}
if (this.preActive === this.navList.length) {
this.preActive = 0;
}
if (this.nextActive === this.navList.length) {
this.nextActive = 0;
}
this.showData.splice(this.num, 1, this.navList[this.preActive]);
this.num++;
this.preActive++;
this.nextActive++;
this.$nextTick(() => {
this.positionArr.unshift(this.positionArr[this.positionArr.length - 1]);
this.positionArr.pop();
for (let i = 0; i < this.itemArr.length; i++) {
this.startMove(this.itemArr[i], {
left: this.positionArr[i][0],
top: this.positionArr[i][1],
opacity: this.positionArr[i][2]
});
}
});
},
nextItem () {
if (this.num === 0) {
this.num = this.showData.length;
}
if (this.nextActive === 0) {
this.nextActive = this.navList.length;
}
if (this.preActive === 0) {
this.preActive = this.navList.length;
}
this.num--;
this.preActive--;
this.nextActive--;
this.showData.splice(this.num, 1, this.navList[this.nextActive]);
this.$nextTick(() => {
this.positionArr.push(this.positionArr[0]);
this.positionArr.shift();
for (let i = 0; i < this.itemArr.length; i++) {
this.startMove(this.itemArr[i], {
left: this.positionArr[i][0],
top: this.positionArr[i][1],
opacity: this.positionArr[i][2]
});
}
});
},
startMove (obj, json) {
for (let attr in json) {
let cur = 0;
if (attr === 'opacity') {
cur = Math.round(parseFloat(this.getStyle(obj, attr)) * 100);
} else {
cur = parseInt(this.getStyle(obj, attr));
}
let speed = (json[attr] - cur);
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if (attr === 'opacity') {
obj.style.opacity = cur + speed;
} else {
obj.style[attr] = cur + speed + 'px';
}
}
}
}
};
</script>
<style scoped lang="scss">
$url: '~@/assets/images/importantEvent/';
.venue-wrap {
position: relative;
z-index: 10;
height: 100%;
.nav-wrap {
position: relative;
height: 100%;
padding-top: 268px;
.prev,
.next {
position: absolute;
width: 66px;
height: 66px;
top: 450px;
background: rgba(0, 186, 255, 0.1);
border-radius: 50%;
background-repeat: no-repeat no-repeat;
background-position: center center;
border: 1px solid transparent;
cursor: pointer;
&:hover {
border-color: #00baff;
}
}
.prev {
background-image: url($url+'home/icon_banner_left.png');
left: 150px;
}
.next {
background-image: url($url+'home/icon_banner_right.png');
right: 150px;
}
.nav-list {
position: relative;
width: 1202px;
height: 100%;
margin: 0 auto;
overflow: hidden;
}
.item {
position: absolute;
width: 263px;
height: 324px;
background-image: url($url+'venueSecurity/border_out.png');
background-repeat: no-repeat no-repeat;
background-size: 100% 100%;
transition: all 0.5s;
left: -313px;
top: 424px;
opacity: 0;
&.item0 {
left: -313px;
top: 424px;
opacity: 0;
}
&.item1 {
left: 0;
top: 82px;
opacity: 1;
}
&.item2 {
left: 313px;
top: 0;
opacity: 1;
}
&.item3 {
left: 626px;
top: 0;
opacity: 1;
}
&.item4 {
left: 939px;
top: 82px;
opacity: 1;
}
&.item5 {
left: 1252px;
top: 424px;
opacity: 0;
}
}
}
}
</style>