前言
轮播组件是常见的一种方式,用来展示图像、信息或者是广告。我们可以使用React来创建一个轮播组件,并且利用其中的State和effect Hook来创建一款动态的、可以自动播放的轮播组件。
效果
轮播组件会展示一个平铺的图片列表。在图片列表下方是一组小圆点,每个小圆点对应一个图片。当一个新的图片显示时,相对应的小圆点会高亮。组件会每隔一段时间自动切换图片,并且当它切换到最后一张图片后,会继续切回第一张图片。
原理分析
轮播组件的实现依赖于React的**useState
和useEffect
**这两个Hook。
- 我们首先通过**
useState
创建一个index
变量以及一个setIndex
函数。index
**记录了我们当前展示图片的位置。 - 下面我们会创建一个名为**
list
**的变量,它会把图片数组中第一张图片复制一份添加到数组末尾。 - 接下来我们在**
useEffect
中设置一个定时任务,每隔2秒钟更新一次index
**的值,等于在每两秒钟播放下一张图片。 - 最后,我们根据**
index
的值,来计算需要平移的比例,然后定义一个transform
** CSS属性,此步骤定义了图片滚动所需要的动画效果。
代码实现
- 首先,我们导入所需的模块以及定义图片数据。
import React, { useState } from "react";
import classnames from "classnames";
import "./index.less";
const dataSource = [
{
picture:
"<https://cdn.fmlg1688.cn/build-material/3c76b0a215c64baebded1a690e1ff989.blob>",
title: "是怎么做出来的",
},
{
picture:
"<https://cdn.fmlg1688.cn/build-material/image/b3528a0b59f34e32aa4aae4652bee76f.jpeg>",
title: "成功案例",
},
{
picture:
"<https://cdn.fmlg1688.cn/build-material/3c76b0a215c64baebded1a690e1ff989.blob>",
title: "仿木栏杆-03",
},
];
- 然后实现轮播组件的代码:
export default function Carousel() {
const [index, setIndex] = useState(0);
const carouselRef = useRef<HTMLDivElement>(null);
const list = useMemo(() => {
return [...dataSource, dataSource[0]];
}, [dataSource]);
useEffect(() => {
const goNext = () => {
setTimeout(() => {
if (index + 1 === list.length) {
if (carouselRef.current?.style) {
carouselRef.current.style.transform = "translateX(0%)";
}
setIndex(0);
} else {
setIndex(index + 1);
if (index + 1 === list.length - 1) {
setTimeout(() => {
setIndex(0);
}, 300);
}
}
// setIndex((inx) => {
// if (inx + 1 === list.length) {
// return 0;
// } else {
// if (inx + 1 === list.length) {
// goNext();
// }
// ret
// });
}, 2000);
};
goNext();
}, [index]);
console.log("index:", index);
return (
<div className="carousel-container">
<div
ref={carouselRef}
className="carousel"
style={{
width: `${100 * list.length}%`,
transform: `translateX(-${(100 / list.length) * index}%)`,
transition: 0 === index ? `` : "transform 0.3s",
}}
>
{list.map((data) => {
return (
<div className="carousel-item">
<img src={data.picture} />
</div>
);
})}
</div>
<ul className="dot">
{dataSource.map((data, inx) => {
return (
<li
className={classnames("dot-item", {
"dot-item--active": index === inx,
})}
></li>
);
})}
</ul>
</div>
);
}
export default function Carousel() {
const [index, setIndex] = useState(0);
const carouselRef = useRef<HTMLDivElement>(null);
const list = useMemo(() => {
return [...dataSource, dataSource[0]];
}, [dataSource]);
useEffect(() => {
const goNext = () => {
setTimeout(() => {
if (index + 1 === list.length) {
if (carouselRef.current?.style) {
carouselRef.current.style.transform = "translateX(0%)";
}
setIndex(0);
} else {
setIndex(index + 1);
if (index + 1 === list.length - 1) {
setTimeout(() => {
setIndex(0);
}, 300);
}
}
}, 2000);
};
goNext();
}, [index]);
console.log("index:", index);
return (
<div className="carousel-container">
<div
ref={carouselRef}
className="carousel"
style={{
width: `${100 * list.length}%`,
transform: `translateX(-${(100 / list.length) * index}%)`,
transition: 0 === index ? `` : "transform 0.3s",
}}
>
{list.map((data) => {
return (
<div className="carousel-item">
<img src={data.picture} />
</div>
);
})}
</div>
<ul className="dot">
{dataSource.map((data, inx) => {
return (
<li
className={classnames("dot-item", {
"dot-item--active": index === inx,
})}
></li>
);
})}
</ul>
</div>
);
}
在这个组件中:
- 我们定义了一个React引用**
carouselRef
**,通过这个引用我们可以获取到对应渲染的DOM对象。 - 在每2秒钟,我们通过**
goNext
函数来触发轮播图的切换。有一个特别的处理,当轮播切换到复制的第一张图片时,改变index
**到0并且立即清除过渡效果,使得轮播图看起来像是循环播放的。 - 当创建轮播组件的HTML部分时,我们基于**
index
值增加transform
和transition
**样式,通过CSS动画实现了轮播的滚动效果。 - 最后我们定义了一个小圆点列表,它的作用是表示当前显示的是哪张图片。小圆点的数量等于图片的数量,但是并不包括复制的第一张图片。哪个小圆点处于活动状态是基于**
index
**值确定的。
总结
以上就是通过React实现轮播图的方法。这个轮播图基于React的**useState
和useEffect
实现,利用了transform
和transition
**来呈现滑动的动画效果。