如何使用React类组件和Tailwind CSS创建一个旋转木马
旋转木马是一种循环播放一系列内容的幻灯片。这些内容可以是图片、文本或视频。通过使用上一个和下一个控件,可以从一个旋转木马的幻灯片过渡到另一个。过渡也可以通过使用定时器来自动进行。
在这篇文章中,我们将使用React类组件创建一个旋转木马组件,并使用Tailwind CSS进行样式设计。React是一个JavaScript库,用于创建用户界面。
Tailwind CSS是一个CSS框架,使用实用类来设计网页的样式
目标
- 使用React类组件创建一个旋转木马。
- 使用Tailwind CSS对旋转木马进行样式设计。
- 实现旋转木马的自动播放功能。
- 在移动设备上实现滑动功能。
前提条件
要跟上本教程,你将需要。
- React的基本知识。
- 中级CSS知识。
- 一个代码编辑器,最好是[VS Code]。
- 一个浏览器,最好是Chrome。
- 在你的机器上安装[Node.js]。
设置我们的项目
在Windows操作系统中,打开命令提示符,并导航到你想创建项目的位置。然后运行以下命令。
npx create-react-app react-tailwind-carousel
上面的命令将创建我们的React项目。
键入下面的命令来导航到项目目录。
cd react-tailwind-carousel
如果你使用的是VS Code,在命令提示符下键入以下命令,或者打开你的代码编辑器并打开包含项目的文件夹。
code .
打开集成终端,键入以下命令,在开发服务器上打开该项目。
npm run start
上面的命令,默认情况下,在localhost 3000端口启动项目。打开浏览器,输入以下地址:http://localhost:3000。如果你看到旋转的反应标志和它下面的一些文字,这意味着项目已经成功设置了。
下一步是在我们的项目中安装Tailwind CSS。
安装依赖项
以下是我们将在我们的项目中使用的依赖项。
- react-icons - 我们将使用这个包来获得下一个和上一个图标。
- react-easy-swipe - 我们将使用这个包来实现移动设备上的刷卡功能。
运行下面的命令来安装它们。
npm install react-icons react-easy-swipe
创建旋转木马
由于所有的组件都是默认的功能组件。打开App.js 组件并清除一切。然后粘贴以下代码。
import React, { Component } from "react";
export default class App extends Component {
render() {
return <div className="flex justify-center"></div>;
}
}
上面的代码显示了我们如何定义一个类组件。这是根组件,我们将把其他组件导入这个组件中,以呈现给用户。
这个div有两个样式应用于它。这些样式有助于使组件在整个网页上水平居中。
接下来,打开src 文件夹,创建一个名为**component/**的文件夹。我们将在这里创建所有单独的组件。
在组件文件夹中,创建两个组件。
- CarouselData.js - 这个组件将保存旋转木马的所有数据。它将是一个数组,包含我们将在旋转木马中显示的不同图片的链接。
- Carousel.js - 这个组件将包含旋转木马的所有互动元素,包括下一个和上一个按钮、滑动指示器以及旋转木马的所有功能。
创建CarouselData.js组件
打开CarouselData.js文件,粘贴以下代码。
export const CarouselData = [
{
image:
"https://images.unsplash.com/photo-1546768292-fb12f6c92568?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
},
{
image:
"https://images.unsplash.com/photo-1501446529957-6226bd447c46?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1489&q=80",
},
{
image:
"https://images.unsplash.com/photo-1483729558449-99ef09a8c325?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1350&q=80",
},
{
image:
"https://images.unsplash.com/photo-1475189778702-5ec9941484ae?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1351&q=80",
},
{
image:
"https://images.unsplash.com/photo-1503177119275-0aa32b3a9368?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1350&q=80",
},
];
上面的代码是一个对象数组,包含了我们将在旋转木马中显示的图片的链接。
创建Carousel.js组件
打开Carousel.js组件,粘贴以下代码。
import React, { Component } from "react";
import { CarouselData } from "./CarouselData";
import { AiOutlineLeft, AiOutlineRight } from "react-icons/ai";
import Swipe from "react-easy-swipe";
class Carousel extends Component {
constructor(props) {
super(props);
this.state = {
currentSlide: 0,
};
}
render() {
return (
<div className="mt-8">
<div className="max-w-lg h-72 flex overflow-hidden relative">
{CarouselData.map((slide, index) => {
return (
<img
src={slide.image}
alt="This is a carousel slide"
key={index}
className={
index === this.state.currentSlide
? "block w-full h-auto object-cover"
: "hidden"
}
/>
);
})}
</div>
</div>
);
}
}
export default Carousel;
我们首先导入CarouselData 组件,以获得将在旋转木马中显示的图片。
然后,我们从react-icons 包中导入左和右箭头。
最后,我们导入Swipe 包,这将帮助我们在移动设备中添加刷卡功能。
在状态部分,我们将活动状态定义为0。该状态将被一个函数修改,该函数将相应地增加或减少它。这将帮助我们决定显示哪个幻灯片。
我们给容器中的div一个类别,即mt-8 ,翻译成margin-top: 2rem。这就使我们的旋转木马远离了顶部的边距。然后我们再创建一个包含各个图片的div。
在这个div里面,我们使用JavaScript数组map() 方法。
在这个例子中,map() 方法需要两个参数:幻灯片--指CarouselData数组中的每个单独的元素,以及索引--指数组中每个单独元素的索引。该方法还需要一个回调,返回设置为src 的图像,slide.image 。
然后我们给图像一个类,在这个类中,我们使用条件渲染来决定我们将显示哪张图像。这是通过使用三元操作符实现的。
这段代码。
className={index===this.state.currentSlide ? 'block w-full h-auto object-cover' : 'hidden'}
翻译为:如果索引(这是map()方法中的一个参数)等于类中定义的currentSlide 状态,则对图像应用类block w-full h-auto object-cover 。否则,将hidden 类应用到图像上。这意味着我们一次只能查看一个图像。
用下面的代码更新App.js ,导入旋转木马组件,并将其渲染到浏览器中。
import React, { Component } from "react";
import Carousel from "./components/Carousel";
export default class App extends Component {
render() {
return (
<div className="flex justify-center">
<Carousel />
</div>
);
}
}
添加下一个和上一个按钮
在浏览器上,我们只能查看一张图片。我们需要添加导航按钮来帮助我们从一张图片移动到另一张。
要做到这一点,在Carousel.js组件中,在包含地图方法的div内添加以下代码。
<AiOutlineLeft className='absolute left-0 text-3xl inset-y-1/2 text-white cursor-pointer' />
<AiOutlineRight className='absolute right-0 text-3xl inset-y-1/2 text-white cursor-pointer' />
我们插入两个箭头,并对它们进行相应的定位。
为了给箭头添加功能,添加onClick 事件监听器,它将监听一个点击事件并导航到相应的幻灯片。
<AiOutlineLeft onClick={this.prevSlide} className='absolute left-0 text-3xl inset-y-1/2 text-white cursor-pointer' />
<AiOutlineRight onClick={this.nextSlide} className='absolute right-0 text-3xl inset-y-1/2 text-white cursor-pointer' />
现在,我们必须创建当我们点击按钮时将被调用的函数。在构造函数方法下,添加以下几行代码。
nextSlide = () => {
let newSlide =
this.state.currentSlide === CarouselData.length - 1
? 0
: this.state.currentSlide + 1;
this.setState({ currentSlide: newSlide });
};
prevSlide = () => {
let newSlide =
this.state.currentSlide === 0
? CarouselData.length - 1
: this.state.currentSlide - 1;
this.setState({ currentSlide: newSlide });
};
nextSlide 函数在用户点击下一个按钮时被调用。
在这个函数中,我们首先定义了一个名为newSlide 的变量。然后我们有条件地给这个变量赋值。如果currentSlide状态等于包含图片的数组的长度,我们将newSlide 的值设置为0。否则,我们将增加currentSlide状态的值。
这有助于确保我们能够不断地循环浏览图片。然后我们使用setState 方法来更新currentSlide的值。
当用户点击上一个按钮时,prevSlide 函数被调用。newSlide变量根据currentSlide状态的值有条件地分配一个值。
假设currentSlide状态等于0,在这种情况下,newSlide变量被分配的值相当于包含图像的数组长度-1(即最后一张图像)。
实现圆点/指示器
这些通常位于旋转木马的底部,用于显示当前的幻灯片和幻灯片的总数。它们也可以用来在幻灯片之间进行导航。
要实现这些圆点,请在包含图片的div中复制以下代码。
<div className="absolute w-full flex justify-center bottom-0">
{CarouselData.map((element, index) => {
return (
<div
className={
index === this.state.currentSlide
? "h-2 w-2 bg-blue-700 rounded-full mx-2 mb-2 cursor-pointer"
: "h-2 w-2 bg-white rounded-full mx-2 mb-2 cursor-pointer"
}
key={index}
onClick={() => {
this.setCurrentSlide(index);
}}
></div>
);
})}
</div>
该代码在数组中循环,为每个元素返回一个div。每个div都有一个onClick 事件监听器,当点击时调用一个setCurrentSlide 函数,并将被点击的div的索引作为一个参数传递。
我们有条件地分配类,以确保活动幻灯片的点与其他的不同。
在prevSlide函数的下面,复制以下代码。
setCurrentSlide = (index) => {
this.setState({ currentSlide: index });
};
上面的函数接收被点击的div的索引作为参数,并使用它来设置currentSlide状态的值。
现在,到浏览器上http://localhost:3000/。你会看到,你可以通过点击小圆点,或者上一个和下一个按钮在不同的图片之间切换。
实现幻灯片的自动播放和悬停时的暂停
要做到这一点,请修改状态部分,使其看起来像这样。
this.state = {
currentSlide: 0,
paused: false,
};
为了实现自动播放,我们将使用javascript的setInterval() 方法和componentDidMount() 方法。
componentDidMount(){
setInterval(() => {
if(this.state.paused === false){
let newSlide = this.state.currentSlide === CarouselData.length - 1 ? 0 : this.state.currentSlide + 1
this.setState({currentSlide: newSlide})
}
}, 3000)
}
在上面的代码中,setInterval() 方法在组件安装时被调用。它只在暂停状态被设置为false时执行。它使用一个条件语句来给newSlide变量赋值,然后将currentSlide状态设置为赋值。它有助于确定要显示的图像。
setInterval() 方法还需要另一个参数,延迟,它决定了代码执行的时间间隔。在本例中,延迟是3000ms,这意味着该函数每隔3秒就执行一次。
为了实现悬停时的暂停,我们将使用onMouseEnter和onMouseLeave事件监听器。在img标签上添加以下事件监听器。
onMouseEnter={() => {
this.setState({paused: true})
}}
onMouseLeave={() => {
this.setState({paused: false})
}}
onMouseEnter 是在你将光标移动到包含图像的区域时触发的。一旦触发,它将暂停状态修改为真,并暂停自动播放。
onMouseLeave 当你把光标从包含图像的区域移开时被触发。一旦触发,它将暂停的状态修改为假,并恢复自动播放。
在移动设备上实现刷屏功能
要做到这一点,我们将使用我们之前安装的react-easy-swipe 包。
将<Swipe></Swipe> 标签放在你想监听刷卡事件的区域周围。在本例中,它是围绕产生图像的map() 方法。
<Swipe onSwipeLeft={this.nextSlide} onSwipeRight={this.prevSlide}>
{CarouselData.map((slide, index) => {
return (
<img
src={slide.image}
alt="This is a carousel slide"
key={index}
className={
index === this.state.currentSlide
? "block w-full h-auto object-cover"
: "hidden"
}
onMouseEnter={() => {
this.setState({ paused: true });
}}
onMouseLeave={() => {
this.setState({ paused: false });
}}
/>
);
})}
</Swipe>
Swipe标签接收onSwipeLeft 和onSwipeRight 属性,并调用适当的函数。
现在你有一个使用React类组件和Tailwind CSS创建的全功能旋转木马。
旋转木马组件的完整代码
import React, { Component } from "react";
import { CarouselData } from "./CarouselData";
import { AiOutlineLeft, AiOutlineRight } from "react-icons/ai";
import Swipe from "react-easy-swipe";
class Carousel extends Component {
constructor(props) {
super(props);
this.state = {
currentSlide: 0,
paused: false,
};
}
componentDidMount() {
setInterval(() => {
if (this.state.paused === false) {
let newSlide =
this.state.currentSlide === CarouselData.length - 1
? 0
: this.state.currentSlide + 1;
this.setState({ currentSlide: newSlide });
}
}, 3000);
}
nextSlide = () => {
let newSlide =
this.state.currentSlide === CarouselData.length - 1
? 0
: this.state.currentSlide + 1;
this.setState({ currentSlide: newSlide });
};
prevSlide = () => {
let newSlide =
this.state.currentSlide === 0
? CarouselData.length - 1
: this.state.currentSlide - 1;
this.setState({ currentSlide: newSlide });
};
setCurrentSlide = (index) => {
this.setState({ currentSlide: index });
};
render() {
return (
<div className="mt-8">
<div className="max-w-lg h-72 flex overflow-hidden relative">
<AiOutlineLeft
onClick={this.prevSlide}
className="absolute left-0 text-3xl inset-y-1/2 text-white cursor-pointer"
/>
<Swipe onSwipeLeft={this.nextSlide} onSwipeRight={this.prevSlide}>
{CarouselData.map((slide, index) => {
return (
<img
src={slide.image}
alt="This is a carousel slide"
key={index}
className={
index === this.state.currentSlide
? "block w-full h-auto object-cover"
: "hidden"
}
onMouseEnter={() => {
this.setState({ paused: true });
}}
onMouseLeave={() => {
this.setState({ paused: false });
}}
/>
);
})}
</Swipe>
<div className="absolute w-full flex justify-center bottom-0">
{CarouselData.map((element, index) => {
return (
<div
className={
index === this.state.currentSlide
? "h-2 w-2 bg-blue-700 rounded-full mx-2 mb-2 cursor-pointer"
: "h-2 w-2 bg-white rounded-full mx-2 mb-2 cursor-pointer"
}
key={index}
onClick={() => {
this.setCurrentSlide(index);
}}
></div>
);
})}
</div>
<AiOutlineRight
onClick={this.nextSlide}
className="absolute right-0 text-3xl inset-y-1/2 text-white cursor-pointer"
/>
</div>
</div>
);
}
}
export default Carousel;
总结
旋转木马是网站的一个重要组成部分,因为它有助于改善用户体验。
在上面的例子中,我们已经涵盖了旋转木马的主要部分。
然而,你可以通过添加动画和在大屏幕上显示一个以上的项目来改进它。