您可能在许多现代应用程序中遇到过轮播。这些多功能网页元素以各种名称(例如滑块或旋转器)而闻名,它们以视觉上吸引人的滑动或旋转方式展示内容。
轮播可以帮助您节省空间、增强用户界面并提供出色的用户体验。
轮播已成为 UI 设计的主要内容,通常用于显示图像、推荐等。创建引人入胜的动态界面时,它们是不可或缺的。
在本文中,我们将深入探讨使用 React 和 Framer Motion 构建图像轮播的过程,指导您完成每一步,为您的应用程序创建令人惊叹的交互式视觉组件。
(更|多优质内|容:java567 点 c0m)
什么是成帧器运动?
这是一个用于 React 应用程序的开源动画库,您可以使用它为我们的 Web 应用程序创建动态和响应式动画。
Framer Motion 有几个有用的功能,包括:
-
动画:这允许您为组件进行无缝过渡。
-
手势:它支持触摸和鼠标动作,允许您考虑某些事件。
-
变体:Framer Motion 使您能够以声明方式声明组件,从而保持代码的组织性和可重用性。
所有这些功能都非常有用,我们很快就会看到它们的实际应用。
要更深入地了解 Framer Motion,您可以浏览其文档和资源。但在本文中,我们将重点关注基础知识。当我指导您了解使用 Framer Motion 的基础知识时,我的主要目标是构建令人印象深刻且引人入胜的图像轮播。
如何设置您的开发环境
我们要做的第一件事是设置您的开发环境。这涉及安装必要的包以成功构建您的应用程序。这包括安装Node.js和npm
如果您已经安装了 Node.js 和 npm,则无需再次下载并安装它们。
创建一个 React 应用程序
此时,我假设您已经安装了 Node 和 npm。要创建 React 应用程序,只需转到终端并访问您希望应用程序所在的目录。然后运行以下命令:
npx create-react-app react-image-carousel
您可以为您的应用程序命名任何您想要的名称 - 但出于本文的目的,我将其命名为react-image-carousel.
成功创建 React 应用程序后,在代码编辑器中打开您的目录。您应该获得一些默认文件和样式,它应该如下所示:
我们不需要此项目中的大部分文件和样式,因此您可以清理以下文件:app.test.js、logo.svg、reportWebVitals.js、setupTest.js。您还可以删除 App.css 表中的所有默认样式。
现在您的 React 应用程序已创建并设置完毕,为此项目设置开发环境的最后一步是安装 Framer Motion。
为此,只需转到终端确保您位于项目目录中并运行以下命令:
npm install framer-motion
这应该安装最新版本的 Framer Motion。现在你应该可以走了。只需用于npm run start在浏览器上启动开发服务器即可。
如何设计图像轮播组件
为了开始设计,我们首先创建一个Carousel.js组件。在轮播组件中,我们将从useStateReact 导入钩子,然后从 Framer Motion导入motion和属性。AnimatePresence
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
然后我们创建 carousel 函数,该函数接受imagesprop,该 prop 是图像 URL 的数组:
const Carousel = ({ images }) => {};
在我们的 carousel 函数中,我们使用 useState 初始化一个状态变量,以跟踪我们用作setCurrentIndex更新索引的相应函数的当前图像索引。
接下来,我们创建 3 个辅助函数来处理用户交互,其中包括:
-
handleNext:这会将 currentIndex 更新为下一个索引,以便更改图像,如果到达数组末尾,则循环返回。
-
handlePrevious:这与handleNext 函数的作用相同,但这次顺序相反。这使我们能够回到图像。
-
handleDotClick:这将索引作为参数并更新 currentIndex。这样,我们只需单击这些点就可以向前和向后跳转到图像。
const Carousel = ({ images }) => {
const [currentIndex, setCurrentIndex] = useState(0);
const handleNext = () => {
setCurrentIndex((prevIndex) =>
prevIndex + 1 === images.length ? 0 : prevIndex + 1
);
};
const handlePrevious = () => {
setCurrentIndex((prevIndex) =>
prevIndex - 1 < 0 ? images.length - 1 : prevIndex - 1
);
};
const handleDotClick = (index) => {
setCurrentIndex(index);
};
这些是我们的组件所需的辅助函数
如何创建我们的模板
我们的模板非常简单,由图像、滑块方向和点(指示器)组成。
return (
<div className="carousel">
<img
key={currentIndex}
src={images[currentIndex]}
/><div className="slide_direction">
<div className="left" onClick={handlePrevious}>
<svg
xmlns="/2000/svg"
height="20"
viewBox="0 96 960 960"
width="20"
>
<path d="M400 976 0 576l400-400 56 57-343 343 343 343-56 57Z" />
</svg>
</div>
<div className="right" onClick={handleNext}>
<svg
xmlns="/2000/svg"
height="20"
viewBox="0 96 960 960"
width="20"
>
<path d="m304 974-56-57 343-343-343-343 56-57 400 400-400 400Z" />
</svg>
</div>
</div>
<div className="indicator">
{images.map((_, index) => (
<div
key={index}
className={`dot ${currentIndex === index ? "active" : ""}`}
onClick={() => handleDotClick(index)}
></div>
))}
</div>
</div>
);
正如您在模板中看到的,我们在当前索引处显示图像。然后我们有一个 div,其中包含两个带有类名和 的slider_directiondiv 。我们将它们创建为轮播的导航按钮。它们使用内联 SVG 来显示箭头图标,并且它们的 onClick 处理程序分别设置为和。leftrighthandlePrevious``handleNext
我们还有一个指示器 div,我们创建它来显示代表轮播中每个图像的一系列点。它映射图像数组并为每个图像创建一个点,为与currentIndex.
然后,我们为每个点附加一个 onClick 处理程序,该处理程序设置handleDotClick为使用点的索引进行调用。
现在这应该是我们的模板。剩下的就是导出 carousel 组件,将其导入到App.js组件中,并添加一些 CSS。然后我们就准备开始制作动画了。
因此,我们只需从组件中导出轮播功能即可Carousel.js。
export default Carousel;
如何使用轮播组件
我们已经创建了轮播组件。但要使用它,我们必须将其导入到我们的 App.js 组件中:
import Carousel from "./Carousel";
之后,我们可以创建图像数组,它将保存我们的图像 URL。
const images = [
"/photos/169647/pexels-photo-169647.jpeg?auto=compress&cs=tinysrgb&w=600",
"/photos/313782/pexels-photo-313782.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"/photos/773471/pexels-photo-773471.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"/photos/672532/pexels-photo-672532.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"/photos/632522/pexels-photo-632522.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"/photos/777059/pexels-photo-777059.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
];
这些只是我从pexels获得的图像- 这就是我们将在这个项目中使用的图像。
接下来,我们添加 App 函数,它将保存我们的应用程序模板。
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Image Carousel using React and Framer Motion</h1>
</header>
<main>
<Carousel images={images} />
</main>
</div>
);
}
export default App;
正如您所看到的,我们的标题仅显示一个标题,显示我们的应用程序的内容。
然后我们有主要部分,其中添加了轮播组件并接受图像数组的道具。如果您还记得,这是我们在轮播组件中用于显示图像的道具。
最后,我们导出 App 组件,以便我们可以在 index.js 文件中使用它。
要在没有样式的情况下查看所有这些,请运行命令npm run start。该应用程序应如下所示:
丑陋吧?是的,我同意你的看法。但只需几行 CSS,这一切就会发生转变。那么让我们深入了解一下吧。
如何添加 CSS
我不想为轮播组件创建单独的样式表,因此我们将在 App.css 文件中完成所有 CSS 操作。不要忘记导入样式表。
import "./App.css"
这是我们的 CSS:
@import url("/css2?family=Oswald:wght@600&display=swap");
.App-header {
font-size: 1rem;
text-align: center;
font-family: "Oswald", sans-serif;
padding-bottom: 2rem;
}
.carousel-images {
position: relative;
border-radius: 10px;
height: 400px;
max-width: 650px;
margin: auto;
overflow: hidden;
}
.carousel-images img {
width: 99%;
height: 99%;
border-radius: 8px;
border: #ff00008e solid 2px;
}
.slide_direction {
display: flex;
justify-content: space-between;
}
.left,
.right {
background-color: #fb666675;
color: #fff;
padding: 10px 8px 8px 13px;
margin: 0 20px;
border-radius: 50%;
position: absolute;
top: 0;
bottom: 0;
margin: auto 10px;
height: 25px;
width: 25px;
}
.left {
left: 0;
}
.right {
right: 0;
}
.carousel-indicator {
margin-top: 20px;
display: flex;
justify-content: center;
gap: 20px;
}
.dot {
background-color: #333;
width: 15px;
height: 15px;
border-radius: 50%;
}
.active {
background-color: #fa2020;
}
这是我们的 CSS 的结果:
您可能会同意,这看起来好多了,而且功能已经齐全。
现在让我们继续使用 Framer Motion 添加动画,使其具有漂亮的滑动外观。
如何向轮播组件添加动画
要开始使用 Framer Motion 制作动画,您必须熟悉一些概念,因为我们将在本节中经常使用它们。这些概念包括:
-
变体:将变体视为一组命名的属性。它的工作是定义元素应该如何显示或动画。您可以创建不同的变体来表示元素的不同视觉状态或动画,例如open、closed、hover等。
-
初始状态:这就是动画开始之前对象所具有的状态。
-
动画:这只是你的对象将要动画的状态,就这么简单。
回到项目,我们将动画添加到轮播组件中。我们已经导入了我们需要的两个属性 -motion和AnimatePresence属性。
我将把本节分为三个部分,因为我们将向代码的三个部分添加动画,包括图像、滑块方向和指示点。
图像动画
为了对图像的退出和进入进行动画处理,我们需要用一个 组件来包装我们的img元素。AnimationPresence这使我们能够在图像离开或进入时添加动画。然后我们motion.像这样将 a 附加到我们的标签上。
<AnimatePresence>
<motion.img key={currentIndex} src={images[currentIndex]} />
</AnimatePresence>;
接下来,我们走出模板并声明我们的变体。
const slideVariants = {
hiddenRight: {
x: "100%",
opacity: 0,
},
hiddenLeft: {
x: "-100%",
opacity: 0,
},
visible: {
x: "0",
opacity: 1,
transition: {
duration: 1,
},
},
exit: {
opacity: 0,
scale: 0.8,
transition: {
duration: 0.5,
},
},
};
如您所见,sliderVariants具有四个属性:
-
hiddenRight:这会将图像的不透明度设置为 0 并将其放置在容器的右侧。
-
hiddenLeft:这与hiddenRight 的作用相同,但这次它设置在左侧。
-
可见:无论图像位于容器中心的哪个位置,都会调用此属性来实现幻灯片动画。
-
exit:此动画控制当另一个图像滑入时从屏幕上删除图像。
现在我们的变体已经设置好了。我们如何知道图像应该从哪里滑入?我们需要设置一个方向状态并根据slide_direction单击的 s 来更新状态。
const [direction, setDirection] = useState('left');
所以我们将方向设置为从左侧开始。这只是合乎逻辑的,因为要显示的第一幅图像将是第一幅图像。然后我们转到辅助函数并根据单击的方向设置方向。
const handleNext = () => {
setDirection("right");
setCurrentIndex((prevIndex) =>
prevIndex + 1 === images.length ? 0 : prevIndex + 1
);
};
const handlePrevious = () => {
setDirection("left");
setCurrentIndex((prevIndex) =>
prevIndex - 1 < 0 ? images.length - 1 : prevIndex - 1
);
};
const handleDotClick = (index) => {
setDirection(index > currentIndex ? "right" : "left");
setCurrentIndex(index);
};
您可能已经注意到,我们不仅仅设置了handleNext和 的状态handlePrevious。我们也为handleDotClick. 因此,每当单击上一个或下一个点时,都会相应地设置方向。
只是提醒一下 - 方向的目的是设置图像的初始状态,以便滑块可以正常工作。
现在我们的方向已经确定,让我们在img元素中使用我们的变体。
<AnimatePresence>
<motion.img
key={currentIndex}
src={images[currentIndex]}
variants={slideVariants}
initial={direction === "right" ? "hiddenRight" : "hiddenLeft"}
animate="visible"
exit="exit"
/>
</AnimatePresence>
所以我们添加variantsprop 并将其设置为等于slideVariants我们创建的。然后我们添加初始属性并将其设置为等于三元运算符。这会将图像的初始状态设置为 或 ,hiddenRight具体hiddenLeft取决于单击的slider_direction是 或dot。
接下来,我们添加 animate 属性,该属性将图像从初始位置动画到我们在属性中设置的位置visible。
最后,我们添加退出属性并将其设置为exit。当新图像进入时,这会将图像动画移出屏幕。
使用 Framer Motion 时可以使用许多道具。您可以查看文档以了解有关它们的更多信息。
完成后,我们的图像轮播应该可以完美运行。
滑块和点动画
我们可以到此为止,但我只想向我的幻灯片方向和点添加一些动画。
const slidersVariants = {
hover: {
scale: 1.2,
backgroundColor: "#ff00008e",
},
};
const dotsVariants = {
initial: {
y: 0,
},
animate: {
y: -10,
scale: 1.3,
transition: { type: "spring", stiffness: 1000, damping: "10" },
},
hover: {
scale: 1.1,
transition: { duration: 0.2 },
},
};
像往常一样,首先我们创建我们的变体。对于slidersVariants我们只需添加一个悬停属性。对于 ,dotsVariants我们有三个属性:initial、animate 和hover。
就像我们对img元素所做的那样,我们将添加motion.元素名称作为前缀,以便使用 Framer Motion。
<div className="slide_direction">
<motion.div
variants={slidersVariants}
whileHover="hover"
className="left"
onClick={handlePrevious}
>
<svg
xmlns="/2000/svg"
height="20"
viewBox="0 96 960 960"
width="20"
>
<path d="M400 976 0 576l400-400 56 57-343 343 343 343-56 57Z" />
</svg>
</motion.div>
<motion.div
variants={slidersVariants}
whileHover="hover"
className="right"
onClick={handleNext}
>
<svg
xmlns="/2000/svg"
height="20"
viewBox="0 96 960 960"
width="20"
>
<path d="m304 974-56-57 343-343-343-343 56-57 400 400-400 400Z" />
</svg>
</motion.div>
</div>;
如您所见,我们添加了变体并将其设置为等于slidersVariants。然后我们使用一个新属性whileHover并将其设置为等于我们在对象中指定的 over 属性slidersVariants。
<motion.div
key={index}
className={`dot ${currentIndex === index ? "active" : ""}`}
onClick={() => handleDotClick(index)}
initial="initial"
animate={currentIndex === index ? "animate" : ""}
whileHover="hover"
variants={dotsVariants}
></motion.div>;
这里我们不只是添加 whileHover 属性。我们还添加了一个initial道具和一个animate对当前图像点进行动画处理的道具,使其脱颖而出。
在我们的slidersVariants对象中,我们指定了弹簧的过渡类型,它在动画过渡发生时赋予其弹性性质。
将所有这些加在一起,我们时尚的图像轮播就准备好了。这是最终结果:
仅供参考,这是轮播组件的完整代码:
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
const Carousel = ({ images }) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [direction, setDirection] = useState(null);
const slideVariants = {
hiddenRight: {
x: "100%",
opacity: 0,
},
hiddenLeft: {
x: "-100%",
opacity: 0,
},
visible: {
x: "0",
opacity: 1,
transition: {
duration: 1,
},
},
exit: {
opacity: 0,
scale: 0.8,
transition: {
duration: 0.5,
},
},
};
const slidersVariants = {
hover: {
scale: 1.2,
backgroundColor: "#ff00008e",
},
};
const dotsVariants = {
initial: {
y: 0,
},
animate: {
y: -10,
scale: 1.2,
transition: { type: "spring", stiffness: 1000, damping: "10" },
},
hover: {
scale: 1.1,
transition: { duration: 0.2 },
},
};
const handleNext = () => {
setDirection("right");
setCurrentIndex((prevIndex) =>
prevIndex + 1 === images.length ? 0 : prevIndex + 1
);
};
const handlePrevious = () => {
setDirection("left");
setCurrentIndex((prevIndex) =>
prevIndex - 1 < 0 ? images.length - 1 : prevIndex - 1
);
};
const handleDotClick = (index) => {
setDirection(index > currentIndex ? "right" : "left");
setCurrentIndex(index);
};
return (
<div className="carousel">
<div className="carousel-images">
<AnimatePresence>
<motion.img
key={currentIndex}
src={images[currentIndex]}
initial={direction === "right" ? "hiddenRight" : "hiddenLeft"}
animate="visible"
exit="exit"
variants={slideVariants}
/>
</AnimatePresence>
<div className="slide_direction">
<motion.div
variants={slidersVariants}
whileHover="hover"
className="left"
onClick={handlePrevious}
>
<svg
xmlns="/2000/svg"
height="20"
viewBox="0 96 960 960"
width="20"
>
<path d="M400 976 0 576l400-400 56 57-343 343 343 343-56 57Z" />
</svg>
</motion.div>
<motion.div
variants={slidersVariants}
whileHover="hover"
className="right"
onClick={handleNext}
>
<svg
xmlns="/2000/svg"
height="20"
viewBox="0 96 960 960"
width="20"
>
<path d="m304 974-56-57 343-343-343-343 56-57 400 400-400 400Z" />
</svg>
</motion.div>
</div>
</div>
<div className="carousel-indicator">
{images.map((_, index) => (
<motion.div
key={index}
className={`dot ${currentIndex === index ? "active" : ""}`}
onClick={() => handleDotClick(index)}
initial="initial"
animate={currentIndex === index ? "animate" : ""}
whileHover="hover"
variants={dotsVariants}
></motion.div>
))}
</div>
</div>
);
};
export default Carousel;
查看GitHub上的 Git 存储库。
这是Netlify上的网站。
资源
我知道可能有些术语或语法不清楚,特别是如果您不熟悉 React 或不熟悉使用 Framer Motion。如果您想了解更多信息,我会推荐以下一些资源:
-
反应文档
-
Framer 运动文档
-
成帧运动课程
结论
在本文中,我们探索了使用 React 和 Framer Motion(动画和手势库)的强大组合来设计引人入胜且响应式图像轮播的过程。
通过合并诸如motion和 之类的组件AnimationPresence,我们能够穿过步骤来构建一个视觉上吸引人的旋转木马。该轮播展示了我们的图像,并通过迷人的动画提供图像之间的平滑过渡,以增强用户体验。
(更|多优质内|容:java567 点 c0m)
标签:React,const,轮播,动画,index,Motion,图像,我们 From: https://www.cnblogs.com/web-666/p/17524997.html