先看效果
完整的项目地址:
最开始使用swiper +css 动画效果不理想
import { Swiper, SwiperSlide } from "swiper/react";
import swiperTop from "../styles/TopSwiper.module.scss";
import swiper, { Autoplay } from "swiper";
swiper.use([Autoplay]);
import "swiper/css";
const imageArr = [
"/static/card-alice.png",
"/static/card-evan.png",
"/static/card-lloyd.png",
"/static/card-russell.png",
"/static/card-alice.png",
"/static/card-evan.png",
"/static/card-lloyd.png",
"/static/card-russell.png",
];
export default () => {
return (
<div className="head-top-swiper">
<Swiper
className={`container swiper-no-swiping`}
autoplay={{
delay: 5000,
}}
loop
spaceBetween={10}
slidesPerView={2}
>
{imageArr.map((image, index) => {
return (
<SwiperSlide key={index} className="pc-slide">
<img src={image} alt="img" />
</SwiperSlide>
);
})}
</Swiper>
<style global jsx>{`
.pc-slide {
width: 372px ;
height: 537px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 40px;
overflow: hidden;
}
.pc-slide img {
width: 372px ;
height: 537px ;
object-fit: contain;
}
`}</style>
<style jsx>{`
.head-top-swiper {
width: calc((100vw - 1200px) / 2 + 429px );
min-width: 800px;
margin-top: 114px;
height: 537px;
}
`}</style>
</div>
);
};
.swiper.container {
.swiper-wrapper {
transition-timing-function: ease-in-out;
}
.swiper-slide-prev {
opacity: 0;
}
.swiper-slide-active {
transform: scale(1);
animation: fadeOut 1s forwards !important;
}
.swiper-slide-next {
transform: scale(0.9);
animation: fadeIn 1s forwards 0.2s !important;
}
.swiper-slide-next + .swiper-slide {
animation: fade 1s forwards 0.2s !important;
}
}
// @keyframes fadeNext {
// 0% {
// transform: translate(-50%) scale(0.9);
// }
// 100% {
// transform: translateY(-50%) scale(0.9);
// }
// }
@keyframes fadeOut {
0% {
opacity: 1;
transform: translateY(-50%) scale(1);
}
100% {
opacity: 0;
transform: translateY(-50%) scale(0.1);
}
}
@keyframes fadeIn {
0% {
transform: scale(0.9);
}
100% {
transform: scale(1) translate3d(-80px,0,0);
}
}
@keyframes fade {
0% {
transform: scale(0.9);
}
100% {
transform: scale(0.9) translateX(-80px);
}
}
然后使用react-sclick 依旧不理想
import React, { PureComponent } from "react";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import Slider from "react-slick";
const settings = {
centerMode: true,
infinite: true,
centerPadding: "0",
slidesToShow: 2,
slidesToScroll: 1,
speed: 1000,
autoplay: true,
autoplaySpeed: 2000,
arrows:false,
swipe: false,
pauseOnHover: false
};
export default class handleSwiper extends PureComponent {
state = {
imageArr: [
"/static/card-alice.png",
"/static/card-evan.png",
"/static/card-lloyd.png",
"/static/card-russell.png",
"/static/card-alice.png",
"/static/card-evan.png",
"/static/card-lloyd.png",
"/static/card-russell.png",
"/static/card-alice.png",
"/static/card-evan.png",
"/static/card-lloyd.png",
"/static/card-russell.png",
],
};
render() {
const { imageArr = [] } = this.state;
return (
<div className="handleSwiper">
<Slider {...settings}>
{imageArr.map((item, idx) => {
return (
<div className={`item`} key={item}>
<img src={item} alt="img" />
</div>
);
})}
</Slider>
<style jsx>
{`
.handleSwiper {
width: calc((100vw - 1200px) / 2 + 429px );
min-width: 800px;
margin-top: 114px;
height: 537px;
}
.item {
width: 378px!important;
height: 537px;
margin-right: 40px;
border-radius: 52px;
overflow: hidden;
}
.item img {
width: 372px;
height: 537px;
object-fit: contain;
}
`}
</style>
</div>
);
}
}
然后手写+react-flip库写依旧不理想
通过修改数组的内容,比如每隔3s将第一个元素的位置改到最后,前三个是固定动画类
这样会导致页面重排重绘 导致页面明显卡顿。抛弃
最后使用手写 利用transition 和动态改变选中类名
import React, { PureComponent } from "react";
import FlipMove from "react-flip-move";
export default class handleSwiper extends PureComponent {
state = {
imageArr: Array(20).fill(' ').map(()=>{
return [ "/static/card-alice.png",
"/static/card-evan.png",
"/static/card-lloyd.png",
"/static/card-russell.png"]
}).flat(),
index: 0,
transition: true
};
computerClass(idx,index) {
if(idx === index) {
return "item-active";
}else if(idx-1== index) {
return "item-next";
}else {
return "item-hidden";
}
}
componentDidMount() {
clearInterval(this.timer);
this.timer = setInterval(() => {
const {index,imageArr} = this.state
let targetIndex = 0
if( index==imageArr.length-2) {
targetIndex = 0;
this.setState({
transition: false,
index: targetIndex,
},()=>{
this.setState({
transition: true
})
})
return false
}else if(index+1<imageArr.length) {
targetIndex = index +1
}
this.setState({
index: targetIndex
});
}, 3000);
}
render() {
const { imageArr = [],index,transition } = this.state;
return (
<FlipMove>
<div className="handleSwiper">
{imageArr.map((item, idx) => {
return (
<div className={`item ${this.computerClass(idx,index)}`} key={item} style={{
transition: transition? `all 0.6s`: 'none'
}}>
<img src={item} alt="img" />
</div>
);
})}
<style jsx>
{`
.handleSwiper {
margin-top: 114px;
width: 100%;
height: 537px;
display: flex;
align-items: center;
transition: all 0.8s;
position: relative;
}
.item {
width: 378px;
height: 537px;
margin-right: 40px;
border-radius: 52px;
overflow: hidden;
}
.item img {
width: 372px;
height: 537px;
object-fit: contain;
}
`}
</style>
</div>
</FlipMove>
);
}
}