In this tutorial, we are going to create the classic slide animation between a list and a detail (eg. a post).
We are going to learn how to:
- activate custom transitions
- map directions (ie. transition between 2 screens) to animations
- code transition animations using VelocityJS
If you’re not familiar with WP-AppKit theme structure, I recommend that you read the doc section dealing with it: https://uncategorized-creations.com/wp-appkit/doc/#264-layout-areas.
The Tools
VelocityJS
There are several ways to animate elements in your apps from CSS animations and transitions to JavaScript animations. I use both in my app themes. For screen transitions, I prefer to use JavaScript animations. It gives me more control over animations (what is animated, when the animation ends…).
More specifically, I use the nifty VelocityJS library. If you don’t know it already, I encourage you to discover this incredible toolbox for motion designers.
To use VelocityJS, just download it from GitHub and drop velocity.min.js in the js folder of your theme. Then edit functions.js to make VelocityJS available as shown below (define is at the very beginning of the file).
define([ 'jquery', 'core/theme-app', 'core/modules/storage', 'core/theme-tpl-tags', 'root/config', 'theme/js/moment.min', 'theme/js/velocity.min' ], function($,App,Storage,TemplateTags,Config,Moment,Velocity) {
Note: this is an example, the libraries you include may differ depending on your theme.
If you are not familiar with using JavaScript in WP-AppKit, there is a doc section about that: https://uncategorized-creations.com/wp-appkit/doc/#346-javascript-in-themes.
WP-AppKit
WP-Appkit doesn’t provide any animations out of the box (we are going to create some in this very tutorial). Instead, it allows to catch the moment between two screens. Doing that, you will be able to know from where you come from and where you go with all app’s necessary elements to be eventually animated.
By default, WP-AppKit replaces a screen by another. To add custom transitions, you have to bypass this adding the following line in functions.js.
App.setParam( 'custom-screen-rendering', true ); // Don't use default transitions and displays for screens
We can now hook into the WP-AppKit transition mechanism.
Hooking Transitions
To hook the WP-AppKit transitions, we use the screen-transition action hook. In that hook, we are going to launch the proper transition according to the previous and next screens.
App.action('screen-transition',function( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { });
Friendly reminder: we are not talking of PHP WordPress hooks but WP-AppKit JavaScript hooks that you will use in functions.js.
screen-transition takes 6 args:
- $wrapper: jQuery object corresponding to the div tag with the app-content-wrapper id. This div element is added automatically by WP-AppKit.
- $current: the previous screen to be hidden. A jQuery object corresponding to div tag with the app-screen class. This div element is added automatically by WP-AppKit.
- $next: the next screen to be shown. A jQuery object corresponding to div tag with the app-screen class. This div element is added automatically by WP-AppKit.
- next_screen: information about the next screen to be shown (eg. screen type).
- current_screen: information about the previous screen to be hidden (eg. screen type).
- $deferred: a jQuery deferred object allowing to resume the screen display after the transition has ended.
Getting the Right Direction
The first thing to do in the screen-transition hook is to identify the direction (eg. coming from archive and going to single).
For that, we use the getTransitionDirection() method with the current_screen and previous_screen args.
App.action('screen-transition',function( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { // Get the direction keyword from current screen and previous screen var direction = App.getTransitionDirection( next_screen, current_screen ); });
getTransitionDirection() returns keywords like next-screen and previous-screen. (You may even add yours.) So we are going to launch the proper transition according to the returned keyword.
App.action('screen-transition',function( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { // Get the direction keyword from current screen and previous screen var direction = App.getTransitionDirection( next_screen, current_screen ); // Launch proper transition switch ( direction ) { case 'next-screen': // eg. Archive to single transition_slide_next_screen($wrapper, $current, $next, next_screen, current_screen, $deferred); break; case 'previous-screen': // eg. Single to archive transition_slide_previous_screen($wrapper, $current, $next, next_screen, current_screen, $deferred); break; default: // Unknown direction transition_default( $wrapper, $current, $next, next_screen, current_screen, $deferred ); break; } });
Note that we have a default transition in case the app has to handle an unknown direction.
Code the Animations
Now that we have identified the directions and mapped them to transitions, let’s code the animations themselves.
To slide from right from left:
- Have the two screens at the same time in the app’s DOM tree (ie. have 2 div elements with the app-screen class). The next screen is hidden on the right. Both are in the wrapper.
transition_slide_next_screen = function ( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { $wrapper.append($next); // Add the next screen to the DOM / Mandatory first action (notably to get scrollTop() working) // 1. Prepare next screen (the destination screen is not visible. We are before the animation) // Hide the single screen on the right $next.css({ left: '100%' }); // 2. Animate to display next screen // Slide screens wrapper from right to left $wrapper.velocity({ left: '-100%' },{ duration: 300, easing: 'ease-out', complete: function () { // remove the screen that has been transitioned out $current.remove(); // remove CSS added specically for the transition $wrapper.attr( 'style', '' ); $next.css({ left: '', }); $deferred.resolve(); // Transition has ended, we can pursue the normal screen display steps (screen:showed) } }); }
- Slide the screens’ wrapper to reveal the next screen (ie. div with the app-content-wrapper class). To slide we use VelocityJS moving the wrapper from 0 to -100% (to hide the previous screen and reveal the next one). The transition’s duration is 300 ms and we apply the ease-out easing.
transition_slide_next_screen = function ( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { $wrapper.append($next); // Add the next screen to the DOM / Mandatory first action (notably to get scrollTop() working) // 1. Prepare next screen (the destination screen is not visible. We are before the animation) // Hide the single screen on the right $next.css({ left: '100%' }); // 2. Animate to display next screen // Slide screens wrapper from right to left $wrapper.velocity({ left: '-100%' },{ duration: 300, easing: 'ease-out', complete: function () { // remove the screen that has been transitioned out $current.remove(); // remove CSS added specically for the transition $wrapper.attr( 'style', '' ); $next.css({ left: '', }); $deferred.resolve(); // Transition has ended, we can pursue the normal screen display steps (screen:showed) } }); }
- Now we can delete the previous screen from the app’s DOM tree and use the jQuery deferred object to resume the normal app’s event flow. For that we use the VelocityJS complete which is fired as soons as our transition ends.
transition_slide_next_screen = function ( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { $wrapper.append($next); // Add the next screen to the DOM / Mandatory first action (notably to get scrollTop() working) // 1. Prepare next screen (the destination screen is not visible. We are before the animation) // Hide the single screen on the right $next.css({ left: '100%' }); // 2. Animate to display next screen // Slide screens wrapper from right to left $wrapper.velocity({ left: '-100%' },{ duration: 300, easing: 'ease-out', complete: function () { // remove the screen that has been transitioned out $current.remove(); // remove CSS added specically for the transition $wrapper.attr( 'style', '' ); $next.css({ left: '', }); $deferred.resolve(); // Transition has ended, we can pursue the normal screen display steps (screen:showed) } }); }
Sliding from left to right is almost the same.
transition_slide_previous_screen = function ( $wrapper, $current, $next, next_screen, current_screen, $deferred ) { $wrapper.prepend($next); // Add the next screen to the DOM / Mandatory first action (notably to get scrollTop() working) // 1. Prepare next screen (the destination screen is not visible. We are before the animation) // Hide the archive screen on the left $next.css( { left: '-100%' } ); // 2. Animate to display next screen // Slide screens wrapper from left to right $wrapper.velocity({ left: '100%' },{ duration: 300, easing: 'ease-out', complete: function () { // remove the screen that has been transitioned out $current.remove(); // remove CSS added specically for the transition $wrapper.attr( 'style', '' ); $next.css( { left: '', } ); $deferred.resolve(); // Transition has ended, we can pursue the normal screen display steps (screen:showed) } }); }
Et voilà! We have now a nice sliding transition for our theme 🙂 Happy coding!
I am having trouble applying the above code to the bootstrap tutorial theme. Is there an example?
Hi Jon, the above code is an example that can be used with the “WPAK-Off-Canvas” demo theme, but not directly with the “Bootstrap” demo theme.
As each WP-AppKit theme defines its own HTML structure, implementing screen transitions (which are JS/CSS animations of DOM) is slightly different for each theme.
An example of how to implement screen transitions on Bootstrap theme can be found here : https://github.com/mleroi/wpak-theme-bootstrap/tree/feature-screen-transitions.
But note that for now this is more an experimentation than a really usable version of “Bootstrap theme with transitions”, which may come later.