<swiper class="scroll" style=" height: 280px" previous-margin="100rpx" next-margin="100rpx" :current="currentIndex" :autoplay="true" :circular="true" @change="swiperChange" @animationfinish="animationfinish">
<swiper-item v-for="(item, index) in list" :key="index" @click="toDetail(item)">
<view class="swiper-flex-item" :style="{
'align-items':
(currentIndex == index && !isChange) || (indexParse(1) == index && isChange)
? 'center'
: (indexParse(1) == index && !isChange) || (indexParse(2) == index && isChange)
? 'flex-start'
: ''
}">
<view :class="['swiper-image', currentIndex == index ? 'active-image' : '']" :style="{
height: currentIndex == index ? activeImageHeight + 'px' : activeImageHeight * 0.9 + 'px',
width: currentIndex == index ? '' : activeImageHeight * 0.9 + 'px',
'margin-top': currentIndex == index ? 0 : activeImageHeight * 0.05 + 'px'
}">
<view :class="currentIndex == index ? '' : 'swiper-mask'"></view>
</view>
</view>
</swiper-item>
</swiper>
data() {
return {
list: ["", "", "", "", ""],
currentIndex: 0,
activeImageHeight: 200,
isChange: false
}
},
methods: {
swiperChange() {
this.isChange = true;
},
animationfinish(e) {
this.currentIndex = e.detail.current;
this.isChange = false;
},
indexParse(index) {
return parseInt((this.currentIndex + index + this.list.length) % this.list.length);
}
}
.swiper-flex-item {
margin-top: 7px;
border-radius: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
.swiper-image {
width: 100%;
border-radius: 20rpx;
transition: height 0.5s;
background: red;
position: relative;
background-repeat: no-repeat;
}
.swiper-mask {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 10000;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.6);
}
.active-image {
width: 60%;
}
}
<template>
<view class="home">
<view class="home-module">
<image class="home-module-bg" :src="渐变背景图" mode="widthFix"></image>
<view class="swiper" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
<view :class="{'left-current':1==status,'left-right':2==status}" class="left-item"
@click="indexChange(leftIndex)">
<view class="flex-column-center ">
<image class="logo" :src="$util.img(modules[leftIndex].img)">
</image>
<view>{{modules[leftIndex].title}}</view>
</view>
</view>
<view class="current-item"
:class="{'current-right':1==status,'current-left':2==status,'active':0===status}">
<view class="flex-column-center">
<image class="logo"
:src="$util.img(0==status ? modules[currentIndex].imgActive:modules[currentIndex].img)">
</image>
<view>{{modules[currentIndex].title}}</view>
</view>
</view>
<view class="right-item" :class="{'right-left':1==status,'right-current':2==status}"
@click="indexChange(rightIndex)">
<view class="flex-column-center ">
<image class="logo" :src="$util.img(modules[rightIndex].img)">
</image>
<view>{{modules[rightIndex].title}}</view>
</view>
</view>
</view>
<view class="content">
<swiper :style="{height:contentHeight}" circular :current="currentIndex" @change="swiperChange">
<swiper-item>
<view class="item">
index=0的内容
</view>
</swiper-item>
<swiper-item>
<view class="item">
index=1的内容
</view>
</swiper-item>
<swiper-item>
<view class="item">
index=2的内容
</view>
</swiper-item>
<swiper-item>
<view class="item">
index=3的内容
</view>
</swiper-item>
<swiper-item>
<view class="item">
index=4的内容
</view>
</swiper-item>
</swiper>
</view>
</view>
</view>
</template>
<script>
const MAPS = [{
title: 'xxx0',
img: '图标',
imgActive: '高亮图标'
},
{
title: 'xxx1',
img: '图标',
imgActive: '高亮图标'
},
{
title: 'xxx2',
img: '图标',
imgActive: '高亮图标'
},
{
title: 'xxx3',
img: '图标',
imgActive: '高亮图标'
},
{
title: 'xxx4',
img: '图标',
imgActive: '高亮图标'
}
];
export default {
data() {
return {
modules: MAPS,
status: 0,
leftIndex: 0,
rightIndex: 2,
currentIndex: 1,
bannerIndex: 0,
contentHeight: ''
}
},
onShow() {
this.getInfo();
},
methods: {
// 获取swiper高度
initConentHeight() {
setTimeout(() => {
uni.createSelectorQuery()
.in(this)
.select('.item')
.boundingClientRect(data => {
if (data) {
this.contentHeight = data.height + 'px'
}
})
.exec();
}, 100)
},
getInfo() {
// 根据需要判断是否需要调用接口
this.initConentHeight()
},
swiperChange(e) {
this.indexChange(e.detail.current)
},
touchStart(event) {
// 记录触摸起始点的横坐标
this.startX = event.touches[0].clientX;
},
touchMove(event) {
// 计算滑动距离
const currentX = event.touches[0].clientX;
const deltaX = currentX - this.startX;
// 判断滑动方向
if (deltaX > 30) {
this.status = 1
} else if (deltaX < -30) {
this.status = 2
}
},
touchEnd() {
if (1 === this.status) {
this.currentIndex = 0 === this.currentIndex ? this.modules.length - 1 : this.currentIndex - 1;
} else if (2 === this.status) {
this.currentIndex = this.currentIndex === this.modules.length - 1 ? 0 : this.currentIndex + 1
}
this.getInfo()
setTimeout(() => {
this.status = 0
this.leftIndex = 0 === this.currentIndex ? this.modules.length - 1 : this.currentIndex - 1
this.rightIndex = this.currentIndex === this.modules.length - 1 ? 0 : this.currentIndex + 1
}, 500)
},
indexChange(current) {
if (this.currentIndex !== current) {
this.status = ((this.currentIndex > current && !(this.modules
.length - 1 === this.currentIndex && 0 === current)) || (0 === this
.currentIndex && this.modules
.length - 1 === current)) ? 1 : 2
this.currentIndex = current
this.getInfo()
setTimeout(() => {
this.status = 0
this.leftIndex = 0 === this.currentIndex ? this.modules.length - 1 : this.currentIndex -
1
this.rightIndex = this.currentIndex === this.modules.length - 1 ? 0 : this
.currentIndex + 1
}, 500)
}
}
}
}
</script>
<style lang="scss" scoped>
.home {
position: relative;
&-module {
position: relative;
&-bg {
width: 100%;
margin-top: 120rpx;
}
.swiper {
width: 100%;
position: absolute;
top: 50rpx;
left: 0;
.logo {
width: 122rpx;
height: 122rpx;
}
view {
color: #8494CF;
font-size: 30rpx;
font-weight: 600;
}
.active {
view {
color: #fff;
}
}
.current-item,
.left-item,
.right-item {
width: 33.34%;
height: 200rpx;
}
.current-item {
position: absolute;
top: 0;
left: 33.34%;
}
.current-right {
animation: currentRight 0.5s linear forwards;
@keyframes currentRight {
0% {
top: 0;
left: 50%;
transform: rotate(0deg);
}
100% {
top: 50rpx;
left: 68%;
transform: rotate(25deg);
}
}
}
.current-left {
animation: currentLeft 0.5s linear forwards;
@keyframes currentLeft {
0% {
top: 0;
left: 50%;
transform: rotate(0deg);
}
100% {
top: 50rpx;
left: 0;
transform: rotate(-25deg);
}
}
}
.left-item {
position: absolute;
top: 50rpx;
left: 0;
transform: rotate(-25deg);
}
.left-current {
animation: leftCurrent 0.5s linear forwards;
@keyframes leftCurrent {
0% {
top: 50rpx;
left: 0;
transform: rotate(-25deg);
}
100% {
top: 0;
left: 33.34%;
transform: rotate(0deg);
}
}
}
.left-right {
animation: leftHide 0.5s linear forwards, rightShow 0.3s linear forwards 0.25s;
@keyframes leftHide {
0% {
top: 50rpx;
left: 0;
transform: rotate(-25deg);
}
100% {
top: 100rpx;
left: -20%;
transform: rotate(0deg);
opacity: 0;
}
}
@keyframes rightShow {
0% {
top: 100rpx;
left: 100%;
transform: rotate(0deg);
opacity: 0;
}
100% {
top: 50rpx;
left: 68%;
transform: rotate(25deg);
opacity: 1;
}
}
}
.right-item {
position: absolute;
top: 50rpx;
left: 68%;
transform: rotate(25deg);
}
.right-left {
animation: rightHide 0.5s linear forwards, leftShow 0.3s linear forwards 0.25s;
@keyframes rightHide {
0% {
top: 50rpx;
left: 68%;
transform: rotate(25deg);
}
100% {
top: 100rpx;
left: 100%;
transform: rotate(0deg);
opacity: 0;
}
}
@keyframes leftShow {
0% {
top: 100rpx;
left: -33.34%;
transform: rotate(0deg);
opacity: 0;
}
100% {
top: 50rpx;
left: 0;
transform: rotate(-25deg);
opacity: 1;
}
}
}
.right-current {
animation: rightCurrent 0.5s linear forwards;
@keyframes rightCurrent {
0% {
top: 50rpx;
left: 68%;
transform: rotate(25deg);
}
100% {
top: 0;
left: 33.34%;
transform: rotate(0deg);
}
}
}
}
.content {
width: calc(99.9% - 60rpx);
min-height: 240px;
position: absolute;
top: 380rpx;
left: 30rpx;
.share-img {
width: 99.9%;
overflow: hidden;
border-radius: 30rpx;
}
.item {
background-color: #fff;
border-radius: 30rpx;
padding: 30rpx;
}
button {
width: 50%;
margin: 0 auto;
}
}
.empty {
padding: 80rpx 0 50rpx;
}
}
}
</style>
一个个切换
<swiper class="swiper flex-align" autoplay="true" :interval="1000" :current="currentIndex"
:circular="true" @animationfinish="swiperChange">
<swiper-item class="swiper-item" v-for="(item, index) in prizes" :key="index"
@click="toDetail(item)">
<image class="swiper-image" :src="item.thumbnail_image" mode="aspectFit"></image>
</swiper-item>
</swiper>

swiperChange(e) {
this.currentIndex = e.detail.current;
}
/deep/ swiper-item {
width: 130rpx !important;
padding-right: 20rpx !important;
}
.swiper {
height: 130rpx;
.swiper-item {
border-sizing: border-box;
.swiper-image {
width: 130rpx;
height: 130rpx;
border-radius: 20rpx;
}
}
}
效果图:
动画从左向右滚动
<view class="image-animation">
<view class="item">
<view class="swiper-image" v-for="(item,index) in prizes" :key="index">
<image :src="item.thumbnail_image" mode="aspectFit"></image>
</view>
</view>
</view>
.image-animation {
width: 100%;
height: 130rpx;
white-space: nowrap;
position: relative;
overflow: hidden;
.item {
position: absolute;
animation: imageGif 15s linear infinite;
.swiper-image {
display: inline-block;
margin-right: 20rpx;
image {
position: relative;
display: inline-block;
width: 130rpx;
height: 130rpx;
border-radius: 20rpx;
}
}
@keyframes imageGif {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-100%);
}
}
}
}
效果图: