Unit 7: Animations

So far, your app is stylish, navigable, and well structured. You could leave it here, but animations often mark the difference between beginners and pros. In this unit you will learn how to use out of the box animations with View components.

Property Id

An animation is a change in visual properties that happens over a certain period of time. It must be triggered by a change in your components’ properties, and therefore, by a change in the state. These are the most common properties that are used to trigger animations:

The way to specify animations in your View components is by providing a configuration object to the animation property. This object specifies which property triggers the animation and which animation will be performed for each value. In the example below, the View will be animated when the property visible changes; if true it will fade-in, and if false it will fade-out:

View({animation: {visible: ['fade-in', 'fade-out']}})(
Text()('Animated View')
);

Boolean Property

For Boolean variables you can use an array with two positions, as shown in the previous example. The first position, represents the animation to be displayed when true, and the second, when false. The example below builds upon the one from Unit 4, Visibility section, and adds an animation to the visibility property:

import {app, read, update, readFlavor} from '@onejs-dev/core';
import {View, Input, Text} from '@onejs-dev/components';

const state = {isVisible: true};

const App = () => {
return View({content: {gap: 10}})([
Input({type: 'switch', value: read('isVisible'), onChange: update('isVisible')}),
View({
visible: read('isVisible'),
flavor: readFlavor('primaryGradient'),
style: {padding: 40},
/* Defining the animation */
animation: {visible: ['fade-in', 'fade-out']}
})(Text({flavor: readFlavor('light')})('Toggle visibility'))
]);
};

app({component: App, state: state, theme: {preset: 'oneJS'}});

Other Types of Properties

If you want to animate a property that takes non-Boolean values, create a JavaScript object and provide an animation for each value:

animation: {customProperty: {
    a: 'fade-in',   //When 'customProperty' is equal to 'a' the animation 'fade-in' is triggered
    b: 'fade-out',  //When 'customProperty' is equal to 'b' the animation 'fade-out' is triggered
    c: 'expand'     //When 'customProperty' is equal to 'c' the animation 'expand' is triggered
}}

You can see this in action in the example below:

import {app, read, update, readFlavor} from '@onejs-dev/core';
import {View, Input, Text} from '@onejs-dev/components';

const state = {choice: ''}; 
const options = ['a', 'b', 'c'];

const App = () => {
    return  View({content: {gap: 10}})([
        Input({type: 'list', options: options, value: read('choice'), onChange: update('choice')}),
        View({
            /* Property triggering the animations */
            customProperty: read('choice'), 
            flavor: readFlavor('primaryGradient'),
            style: {padding: 40},
            /* Defining the animation */
            animation: {customProperty: {a: 'fade-in', b: 'fade-out', c: 'expand'}}
        })(Text({flavor: readFlavor('light')})('Animated Block'))
    ]);
};

app({component: App, state: state, theme: {preset: 'oneJS'}});

Preset Animations

To make your life a bit easier, oneJS provides several standard animations. In the previous examples, we have already displayed some of them, such as fade-in, fade-out and expand. You can use the preset animations just by indicating their name as a string in the animation property. The example below showcases the available presets at the moment. We are creating more for future releases. We would love to hear your opinion!

import {app, read, update, readFlavor} from '@onejs-dev/core';
import {View, Input, Text} from '@onejs-dev/components';

const state = {
    inAnimation: 'appear',
    outAnimation: 'disappear',
    isVisible: true
}; 

/* Available preset animations */
const inAnimations = ['apprear', 'subtle-in', 'fade-in', 
    'fade-in-left', 'fade-in-right', 'slide-in-left', 
    'slide-in-right', 'slide-in-up', 'slide-in-down', 
    'expand', 'horizontal-expand', 'vertical-expand'];
const outAnimations = ['disapprear', 'subtle-out', 'fade-out', 
    'fade-out-left', 'fade-out-right', 'slide-out-left', 
    'slide-out-right', 'slide-out-up', 'slide-out-down', 
    'shrink', 'horizontal-shrink', 'vertical-shrink'];

const App = () => {
    return  View({content: {direction: 'column', gap: 10}})([
        Text()('In Animation: '),
        Input({type: 'list', options: inAnimations, value: read('inAnimation'), onChange: update('inAnimation')}),
        Text()('Out Animation: '),
        Input({type: 'list', options: outAnimations, value: read('outAnimation'), onChange: update('outAnimation')}),
        Input({type: 'switch', value: read('isVisible'), onChange: update('isVisible')}),
        View({
            visible: read('isVisible'), 
            flavor: readFlavor('primaryGradient'),
            style: {padding: 40},
            /* Defining the animation */
            animation: {visible: [read('inAnimation'), read('outAnimation')]}
        })(Text({flavor: readFlavor('light')})('Animated Block'))
    ]);
};

app({component: App, state: state, theme: {preset: 'oneJS'}});

Custom Animations

Preset animations are great, but you can also choose to create your own. Under the hood, oneJS is using the standard Web Animations API for the web and React Native’s Animated API for iOS and Android. This means that if you are an advanced user, you can create your own animations using the following parameters:

The example below showcases how a fade-in-left and shrink animation definition would look like in the web. Please, note that the way transform keyframes and easing are specified in React Native differ from web.

import {app, read, update, readFlavor} from '@onejs-dev/core';
import {View, Input, Text} from '@onejs-dev/components';

const state = {isVisible: true}; 

/* Custom animation creation */
const inAnimation = {
    keyframes: {transform: ['translate3d(-100%, 0, 0)', 'none'], opacity: [0, 1]},
    options: {duration: 1000, easing: 'ease'}
};
const outAnimation = {
    keyframes: {scale: [1, 0], opacity: [1, 0]},
    options: {duration: 1000, easing: 'ease-out'},
    style: {display: 'none'}
};

const App = () => {
    return  View({content: {gap: 10}})([
        Input({type: 'switch', value: read('isVisible'), onChange: update('isVisible')}),
        View({
            visible: read('isVisible'), 
            flavor: readFlavor('primaryGradient'),
            style: {padding: 40},
            /* Defining the animation */
            animation: {visible: [inAnimation, outAnimation]}
        })(Text({flavor: readFlavor('light')})('Animated Block'))
    ]);
};

app({component: App, state: state, theme: {preset: 'oneJS'}});

That’s all there is to it. Use the animation property in your View components to breathe new life into your app.