What you'll learn:
_
parameterMath.abs
Let’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.abs
Well, 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
if
statement.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!