What you'll learn:
_ parameterMath.absLet’s complete our swipe prototype.
Currently, our card always bounces back to its original position no matter how far we swipe it.
We want to change it so that if we swipe the card far enough, it’ll keep moving until it disappears. Otherwise, if we only move it a little bit, it’ll bounce back to the original position.
How can we change the code to make that happen?
Currently, in onDragEnd, we always start the animation that moves the x offset of the card to 0.
<Frame
...
onDragEnd={function() {
animControls.start({ x: 0 })
}}
/>
We need to add a conditional here to start a different animation according to how far we have swiped.
How would we determine if the card has been swiped far enough? We’ve done something like this before!
We can get more information about the drag gesture from the parameters of this function. The first parameter is event, the second one is info.
<Frame
...
onDragEnd={function(event, info) {
animControls.start({ x: 0 })
}}
/>
We can get how far we’ve dragged the card using the parameter info. Therefore, we don't need the event parameter.
However, if we simply remove the event parameter, our "info" variable will really be equal to event because the first parameter is event and the second is info.
Try switching info and event while using them., and you'll see that the order of parameters is extremely important.
To solve this, we can change event into an underscore _ .
<Frame
...
onDragEnd={function(_, info) {
animControls.start({ x: 0 })
}}
/>
There’s nothing special about this underscore. It’s a parameter as well, but we usually use it as a placeholder for parameters that we don’t care in the function.
Back to info, since it's an object, we can get the x offset using info.point.x. We can now write our if statement.
<Frame
...
onDragEnd={function(_, info) {
if (info.point.x < 150){
animControls.start({ x: 0 })
} else {
animControls.start({x:200})
}
}}
/>
However, there is still a problem with this. When we drag to the left, the card still bounces back. This occurs because, on the left, the x offset will turn negative.
How do we account for both directions?
Math.absWell, there are many ways. For example, we could add multiple if and else statements, but the simplest method here is to use the absolute value function in the Math library that comes with JavaScript — Math.abs.
<Frame
...
onDragEnd={function(_, info) {
if (Math.abs(info.point.x) < 150){
animControls.start({ x: 0 })
} else {
animControls.start({x:200})
}
}}
/>
The original problem isn't completely fixed yet, but now the card follows the else code path. Instead of disappearing on the left side, the card quickly moves to the right side.
This occurs because when we move the card to the left enough, the absolute value of the negative value is greater than 150. Therefore, the code in the else statement is run.
To fix this, we can add another conditional that tests if the x offset is negative or positive.
<Frame
...
onDragEnd={function(_, info) {
if (Math.abs(info.point.x) < 150){
animControls.start({ x: 0 })
} else {
if (info.point.x <0){
animControls.start({x:-200})
} else {
animControls.start({x:200})
}
}
}}
/>
We can make our code more elegant by using a ternary operator. Instead of this nested if-else statement, we can write something like this:
<Frame
...
onDragEnd={function(_, info) {
if (Math.abs(info.point.x) < 150){
animControls.start({ x: 0 })
} else {
animControls.start({x: info.point.x < 0 ? -200 : 200})
}
}}
/>
There are 5 main components.
Condition
The condition is the boolean comparison inside the parentheses of an
ifstatement.info.point.x < 0 ...
Question mark: ?
You can think of
?as the end of the condition.info.point.x < 0 ? ...
First value
This is the value after the question mark. It will be accessed if the condition is true.
info.point.x < 0 ? -200 ...
Colon: :
You can think of
:as the keywordelse.info.point.x < 0 ? ...
Second value
This is the value after the colon. It will be accessed if the condition is false.
info.point.x < 0 ? -200 : 200
In total, a ternary operator is a condensed version of an if-else statement.
We now have finished creating the "Tinder" swipe with one card. Along the way, you learned about rotation, opacity, useMotionValue, and useAnimation, arrow functions, _, Math.abs, the ternary operator, and more.
In the following posts, we add more cards to make a final result like this!