Boo! Peek-a-boo!
--
Page transitions and swipe back gestures in single page applications.
Making a web app feel “native” is challenging, yet fun. It is challenging because browsers and their technology will fight you every step, fun because all front end developers are masochists in disguise.
This time, the challenge (I mean pain) was about navigating back and forward between our app’s screens using swipe left and swipe right. We did it because Facebook does it, and that is a valid reason.
Here are some things we ran into while trying to create a near native experience for our app.
Architecture
Our app contains Backbone.js wrapped in a Cordova.
We wanted the page to change with smooth transitions, you know like all normal apps do, but that required a custom architecture of our code.
First here are the fundamentals of the web app we’ve created. I’ve prepared a Codepen demo on how it’s working: http://codepen.io/anything/full/VvOjGv/ (without touch events yet).
And now, here are the explanations.
Every time you visit a new page we keep its name in an array — that array will be emptied each time a full page reload is made.
The previous page is only hidden from the view port by transitioning it to the left, like the page of a book, and the new page is faded in (the demo has a div moving over the view).
Once the new page is faded in, we put the previous page just behind the current page with z-index (in the demo there is no need for this).
If you go back, using the button in the UI, we transition the current page to the right, like the page of a book, we remove it first from the history array and then from the DOM, with its events and everything. While transitioning, the previous page shows up, since it was placed behind earlier.
All this helped us show the previous page when the user hits the back button on the exact previous scroll position, without reload and without rebinding all the events.
Engineering
The real reason we wanted a swipe navigation was that navigating back using the back button in the top left corner of the screen is embarrassing, especially on large phones which risk a mid air triple flip floor landing, smashing your coolness along.
So, in order to make the UX better, some iOS native apps like Facebook or Instagram have swipe back gestures, that will get you to the previous view. Snappy.
This is what we made in our hybrid app with the help of hammer.js.
So, what we wanted was to be able to go to the previous page by swiping or panning right. The two gestures above are made possible by hammer.js.
You cannot forge a hammer from feather pod fluff
… so we had some problems we had to tackle.
- Scroll: The element you are trying to detect the touch gestures on is scroll-able and whenever you move your finger up and down the page wants to scroll, but if you drag right, the page needs to stop scrolling and move as your finger moves, but just on the x axis.
- Responsiveness: On the web, especially on old android devices, animating or transitioning needs to happen exclusively, that means nothing else can happen at the same time, especially no DOM manipulation. Of course, this is impossible, but it needs to be very close to no manipulations.
- Testing: If you have the time and privilege to work on such a “cool” feature, prepare yourself for lots of testing and! … finger burning.
- Clicks: What to do when you are transitioning you view and the user taps on a link to show another view?
- Can we swipe here and now: The app is not always in a state where the user can swipe back — for example on the first page that the app was opened on, or in a modal window, or inside a slider.
When all you have is a hammer, everything looks like a nail
.. so here are the main events we had to detect.
Pan right: Detect when you drag your finger to the right. When the “panright” event is fired, set a variable as true.
Pan: Detect every move of your finger when you hold-it down. When “pan ”is fired, if the panright event is triggered also, move the page as your finger pans around.
Pan end / Pan cancel: Is triggered when you release your finger after a pan. When “panend ”or “pancancel”, set the panright variable as false. If the pan was made and the finger moved more that 30% of the viewport, transition the page to the right and call the window.history.back() function, else, snap the page back in it’s original place.
Swipe right: Provided for free by hammer.js it will trigger an event when the swipe action was made. The “swiperight ”event will transition the page to the right as the original back button.
Demo
You can download our app! Go ahead, and be sure to buy some stuff too.
Okay, okay, I’ve also added this functionality in a fork of the previous pen for you to play with, in case you like to play with such things.
Please send this to your mobile phone for a better experience as I do in the Vine above: http://codepen.io/anything/full/grBKwr/
Some questions for you:
- Do you think this article is too detailed or it needs to be more detailed?
- What other Cordova apps do you know?
- Any advice on the code demos above? Fork and show us your skills.
Feel free to fork the pens and share to make the web feel better than native.