Meteor-React-Ionic Mobile App Part 6.1: Tinder Transitions

This is the first step towards building our Tinder clone as I promised in my first post. This was shockingly easy to do with this particular technology stack. This should take you about 5 minutes.

Start by cloning the basic template, or by building your own. Then you’re on your way! You can also try to integrate this with some of the other posts including Passing in Data and User Accounts.

When you’re finished, your app should look like the example to the left (though, noticeably less choppy). I’ll add more functionality in a later post.

NOTE: Be aware that if you clone the repo, there are a few quirks with the meteoric:ionic-sass package that will crash the app the first time you run it. All you have to do to solve this is kill the process and re-run Meteor.

The next step (in a later post) is to add rotation (like you see on Tinder), then we’ll want to add the actual swipe functionality.

Step 1

We’re going make the Home component our Tinder interface. The first thing we should do is render a card, which Ionic kindly provides us. Within your render function, add the following code:

...
return (
<div className="card">
<div className="item item-text-wrap">
This is a basic card with text wrap.
</div>
</div>
)

You should now have a card rendered on your page. Now it’s time to animate that card.

Step 2

We’re going to make this card animate by manipulating state and changing our inline styling object (using translate())that we will set in our card — this is explained in greater detail below. Within state, we’re going to keep track of the x and y coordinates of touch events to move the card along with your finger.

The first step is to set our initial state. We want to keep track of the x and y position of our card, the initial position of our card (so we can subtract the difference between the current position and the start position), and whether or not we are currently dragging the card (to allow it to snap back into place when we are done dragging).

Within our Home component, add the following function:

getInitialState() {
return {
x: 0,
y: 0,
initialX: 0,
initialY: 0,
dragging: "none"
}
},

Then we’re going to need three more functions to change state. We need one for the initial touch event, one for the drag event, and one for the end drag event. Add the following three functions (explained below the code):

moveCardInit(e) {
this.setState({
initialX: e.touches[0].pageX,
initialY: e.touches[0].pageY,
dragging: "none"
})
},
moveCard(e) {
deltaX = (e.touches[0].pageX - this.state.initialX)
deltaY = (e.touches[0].pageY - this.state.initialY)
this.setState({
x: deltaX,
y: deltaY
})
},
moveCardEnd(e) {
this.setState({
x: 0,
y: 0,
dragging: "all 0.5s ease"
})
},

In moveCardInit we’re setting initialX and initialY so we can access them later. We’re going to need those values to subtract the new x and y values from the drag event to find out how far the card has moved from its starting position.

The real meat of this transition is in the moveCard function. In this function, we’re taking the new touch and subtracting it from the old touch to find out how many pixels the card has moved on the x and y axis. Then we’re setting state to reflect that change. Recall that state is originally set to zero.

The last function is what we need to be able to transition our card back to its starting location. Within moveCardEnd we’re resetting state of x and y to zero (so we are translating the card zero pixels) and changing dragging to “all 0.5s ease”, which will make more sense below — this is to make sure the card transitions back into place.

Step 3

Now that we’ve set up our state, we need to set up all our touch events and our styling object. Let’s start by initializing the touch events. In our render function, add the following to the top of our Home.jsx file:

React.initializeTouchEvents(true)

I’ve been told that there are some quirks with React registering touch events. If you run into any issues, try adding “cursor: pointer” to your card class.

Also, as noted by Ben Jones, touch events are not enabled by default on desktop. You need to use a mobile emulator, which Chrome provides.

Next lets create our styles object. Remember that “style” in React takes in an object, not strings:

render() {
let cardStyle = {
transform: "translate(" +
this.state.x + "px," +
this.state.y + "px)",
transition: this.state.dragging
}

...

Within this object, we’re transforming the card object on the x and y axis based in this.state.x and this.state.y, which you remember from above is the difference between the start location of the card and the current location of the card while it’s being dragged.

The last thing is setting transition to this.state.dragging, which as you will recall is either “none” or “all 0.5s ease”. If you are dragging, then it doesn’t transition (because it’s following your finger), but as soon as you stop dragging it transitions back into place over the course of 0.5 seconds.

Step 4

The last step is to attach those functions and the style to the component you’re returning. Within the return statement of your render function, change the following:

return (
<div className="card" onTouchStart={this.moveCardInit} onTouchMove={this.moveCard} onTouchEnd={this.moveCardEnd} style={cardStyle}>
<div className="item item-text-wrap">
This is a basic card with text wrap.
</div>
</div>
)

In this addition, you’re calling moveCardInit when you start your touch event, then calling moveCard when you drag, then when you stop dragging, you call moveCardEnd, which transitions the card back to where it started.

And that’s it! You now have a basic Tinder interface. We’ll make it functional in a later post.


Sam Corcos is the lead developer and co-founder of Sightline Maps, the most intuitive platform for 3D printing topographical maps, as well as LearnPhoenix.io, an advanced tutorial site for building scaleable production apps with Phoenix and React.

Additional