Как создать жест смахивания карты Tinder с помощью React и framer-motion?
Мы можем создать простое приложение Tinder, такое как жест смахивания, используя следующий подход, используя модуль Framer в ReactJS.
Предпосылки:
- Знание JavaScript (ES6)
- Знание HTML/CSS.
- Базовые знания ReactJS.
Крюки Framer, используемые при создании этого приложения:
- Framer useMotionValue
- Использование FramerTransform
- Использование FramerАнимация
Создание приложения React и установка модуля:
Шаг 1: Создайте приложение React с помощью следующей команды.
npx create-react-app tinder-swipe
Шаг 2: После создания папки проекта, т. е. Tinder-swipe, перейдите к ней с помощью следующей команды.
cd tinder-swipe
Шаг 3: После создания приложения ReactJS установите модули фреймов с помощью следующей команды.
npm install framer
Структура проекта: Дерево структуры нашего проекта должно выглядеть так:
Подход:
- Мы собираемся использовать useMotionValue() для перемещения карты, когда пользователь перетаскивает курсор, поскольку все компоненты движения внутренне используют motionValues для отслеживания состояния и скорости анимируемого значения, которое мы собираемся получить с помощью этого хука.
- Мы собираемся использовать хук useTransform() для поворота карты по мере того, как карта движется при перетаскивании, связывая с ней motionValue карты.
- Кроме того, мы собираемся использовать хук useTransform() для изменения непрозрачности карты при ее перемещении, привязав ее к motionValue.
- useAnimation() — это служебный хук, который используется для создания элементов управления анимацией (animControls), которые можно использовать для ручного запуска, остановки и последовательности анимации на карте.
Пример 1:
index.js
import React from "react";import ReactDOM from "react-dom";import "./index.css";import { Frame, useMotionValue, useTransform, useAnimation } from "framer"; // Some styling for the cardconst style = { backgroundImage: "URL( backgroundRepeat: "no-repeat", backgroundSize: "contain", backgroundColor: "#55ccff", boxShadow: "5px 10px 18px #888888", borderRadius: 10, height: 300,}; const App = () => { // To move the card as the user drags the cursor const motionValue = useMotionValue(0); // To rotate the card as the card moves on drag const rotateValue = useTransform(motionValue, [-200, 200], [-50, 50]); // To decrease opacity of the card when swiped // on dragging card to left(-200) or right(200) // opacity gradually changes to 0 // and when the card is in center opacity = 1 const opacityValue = useTransform( motionValue, [-200, -150, 0, 150, 200], [0, 1, 1, 1, 0] ); // Framer animation hook const animControls = useAnimation(); return ( <div className="App"> <Frame center // Card can be drag only on x-axis drag="x" x={motionValue} rotate={rotateValue} opacity={opacityValue} dragConstraints={{ left: -1000, right: 1000 }} style={style} onDragEnd={(event, info) => { // If the card is dragged only upto 150 on x-axis // bring it back to initial position if (Math.abs(info.point.x) <= 150) { animControls.start({ x: 0 }); } else { // If card is dragged beyond 150 // make it disappear // making use of ternary operator animControls.start({ x: info.point.x < 0 ? -200 : 200 }); } }} /> </div> );}; ReactDOM.render(<App />, document.getElementById("root")); |
index.css
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;} .App { text-align: center;} code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;} |
Шаг для запуска приложения: Запустите приложение с помощью следующей команды из корневого каталога проекта.
npm start
Вывод: теперь откройте браузер и перейдите по адресу http://localhost:3000/ , вы увидите следующий вывод:
Пример 2: Создание колоды карт
index.js
import React from "react";import ReactDOM from "react-dom";import "./index.css";import { Frame, useMotionValue, useTransform, useAnimation } from "framer"; // Card component with destructured propsconst Card = ({ image, color }) => { // To move the card as the user drags the cursor const motionValue = useMotionValue(0); // To rotate the card as the card moves on drag const rotateValue = useTransform(motionValue, [-200, 200], [-50, 50]); // To decrease opacity of the card when swiped // on dragging card to left(-200) or right(200) // opacity gradually changes to 0 // and when the card is in center opacity = 1 const opacityValue = useTransform( motionValue, [-200, -150, 0, 150, 200], [0, 1, 1, 1, 0] ); // Framer animation hook const animControls = useAnimation(); // Some styling for the card // it is placed inside the card component // to make backgroundImage and backgroundColor dynamic const style = { backgroundImage: `url(${image})`, backgroundRepeat: "no-repeat", backgroundSize: "contain", backgroundColor: color, boxShadow: "5px 10px 18px #888888", borderRadius: 10, height: 300 }; return ( <div className="App"> <Frame center // Card can be drag only on x-axis drag="x" x={motionValue} rotate={rotateValue} opacity={opacityValue} dragConstraints={{ left: -1000, right: 1000 }} style={style} onDragEnd={(event, info) => { // If the card is dragged only upto 150 on x-axis // bring it back to initial position if (Math.abs(info.point.x) <= 150) { animControls.start({ x: 0 }); } else { // If card is dragged beyond 150 // make it disappear // Making use of ternary operator animControls.start({ x: info.point.x < 0 ? -200 : 200 }); } }} /> </div> );}; const App = () => { const cards = [ { color: "#55ccff" }, { color: "#e8e8e8" }, { color: "#0a043c" }, { color: "black" } ]; return ( <div className="App"> {/* Traversing through cards arrray using map function and populating card with different image and color */} {cards.map((card) => ( <Card image={card.image} color={card.color} /> ))} </div> );}; ReactDOM.render(<App />, document.getElementById("root")); |
Шаг для запуска приложения: Запустите приложение, используя следующую команду из корневого каталога проекта:
npm start
Вывод: теперь откройте браузер и перейдите по адресу http://localhost:3000/ , вы увидите следующий вывод: