Hey guys I wanted to add timer along with these gestures to the following react-spring example. I've been struck with this since a long time. It'll be of great assistance. Also I'm working with makestyles from material ui. It would be an additional help if you can tell me how to convert the css in to make styles too. Link to the code: https://codesandbox.io/embed/j0y0vpz59
import { render } from "react-dom";
import React, { useState, useEffect } from "react";
import { useSprings, animated, interpolate } from "react-spring";
import { useGesture } from "react-use-gesture";
import img1 from "./assets/slideImg1.jpg";
import img2 from "./assets/slideImg2.gif";
import img3 from "./assets/slideImg3.gif";
import img4 from "./assets/slideImg4.jpg";
import "./index.css";
const cards = [
img1,
img2,
img3,
img4,
"https://upload.wikimedia.org/wikipedia/en/thumb/8/88/RWS_Tarot_02_High_Priestess.jpg/690px-RWS_Tarot_02_High_Priestess.jpg",
"https://upload.wikimedia.org/wikipedia/en/d/de/RWS_Tarot_01_Magician.jpg",
];
// These two are just helpers, they curate spring data, values that are later being interpolated into css
const to = (i) => ({
x: 0,
y: i * -4,
scale: 1,
rot: -10 + Math.random() * 20,
delay: i * 100,
});
const from = (i) => ({ x: 0, rot: 0, scale: 1.5, y: -1000 });
// This is being used down there in the view, it interpolates rotation and scale into a css transform
const trans = (r, s) =>
`perspective(1500px) rotateX(30deg) rotateY(${
r / 10
}deg) rotateZ(${r}deg) scale(${s})`;
function Deck() {
const [gone] = useState(() => new Set()); // The set flags all the cards that are flicked out
const [fly, setFly] = useState(false);
const [props, set] = useSprings(cards.length, (i) => ({
...to(i),
from: from(i),
})); // Create a bunch of springs using the helpers above
// Create a gesture, we're interested in down-state, delta (current-pos - click-pos), direction and velocity
const bind = useGesture(
({
args: [index],
down,
delta: [xDelta],
distance,
direction: [xDir],
velocity,
}) => {
const trigger = velocity > 0.2; // If you flick hard enough it should trigger the card to fly out
const dir = xDir < 0 ? -1 : 1; // Direction should either point left or right
if (!down && trigger) gone.add(index); // If button/finger's up and trigger velocity is reached, we flag the card ready to fly out
set((i) => {
if (index !== i) return; // We're only interested in changing spring-data for the current spring
const isGone = gone.has(index);
const x = isGone ? (200 + window.innerWidth) * dir : down ? xDelta : 0; // When a card is gone it flys out left or right, otherwise goes back to zero
const rot = xDelta / 100 + (isGone ? dir * 10 * velocity : 0); // How much the card tilts, flicking it harder makes it rotate faster
const scale = down ? 1.1 : 1; // Active cards lift up a bit
return {
x,
rot,
scale,
delay: undefined,
config: { friction: 50, tension: down ? 800 : isGone ? 200 : 500 },
};
});
if (!down && gone.size === cards.length)
setTimeout(() => gone.clear() || set((i) => to(i)), 600);
}
);
useEffect(() => {
setFly(false);
const timerId = setInterval(() => {
setFly(true);
}, 1000);
return () => clearInterval(timerId);
}, [fly]);
// Now we're just mapping the animated values to our view, that's it. Btw, this component only renders once. :-)
return props.map(({ x, y, rot, scale }, i) => (
<animated.div
key={i}
style={{
transform: interpolate(
[x, y],
(x, y) => `translate3d(${x}px,${y}px,0)`
),
}}
>
{/* This is the card itself, we're binding our gesture to it (and inject its index so we know which is which) */}
<animated.div
{...bind(i)}
style={{
transform: interpolate([rot, scale], trans),
backgroundImage: `url(${cards[i]})`,
}}
/>
</animated.div>
));
}
render(<Deck />, document.getElementById("root"));
//css
* {
box-sizing: border-box;
}
html,
body {
overscroll-behavior-y: contain;
margin: 0;
padding: 0;
height: 100%;
width: 100%;
user-select: none;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir,
helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif;
position: fixed;
overflow: hidden;
}
#root {
background: lightblue;
position: fixed;
overflow: hidden;
width: 100%;
height: 100%;
cursor: url("https://uploads.codesandbox.io/uploads/user/b3e56831-8b98-4fee-b941-0e27f39883ab/Ad1_-cursor.png")
39 39,
auto;
}
#root > div {
position: absolute;
width: 100vw;
height: 100vh;
will-change: transform;
display: flex;
align-items: center;
justify-content: center;
}
#root > div > div {
background-color: white;
background-size: auto 85%;
background-repeat: no-repeat;
background-position: center center;
width: 45vh;
max-width: 300px;
height: 85vh;
max-height: 570px;
will-change: transform;
border-radius: 10px;
box-shadow: 0 12.5px 100px -10px rgba(50, 50, 73, 0.4),
0 10px 10px -10px rgba(50, 50, 73, 0.3);
}
```[enter image description here][1]
[1]: https://i.stack.imgur.com/D77CT.png