Transitions

Published: September 03, 2019
Edited: September 03, 2019

A transition is a gradual change of a property value. Contrary to an animation it is able to accept a dynamic value, whereas animations specify fixed values.

Defining a transition

A transition can be defined by setting it in the template:

static _template() {
    return {
        MyTarget:{ transitions: {x: {duration: 2, timingFunction: 'ease'}, color: {duration: 1} }}
    }
}

Starting a transition

A transition can be started from within a patch:

this.tag('MyObject').patch({ smooth:{ x: 10, color: 0xFFFF0000 }});

Notice that any property name that contains the string color (case insensitive), has values interpolated as ARGB values. This means that you can specify a color animation: {p: 'color', v: {0: 0xFFFF0000, 1: 0xFF0000FF}}.

Or using the setSmooth function:

this.tag('MyObject').setSmooth('x', 10);

If required, the transition settings can also be modified while setting:

this.tag('MyObject').setSmooth('x', 10, {duration: 1});

Or from within a patch:

this.tag('MyObject').patch({ smooth:{ x: [10, { duration: 4, delay: 4, timingFunction: 'linear' } ]}});

Removing a transition

Remove a transition by setting undefined instead of the settings:

this.tag('MyObject').patch({ transitions:{ x: null }});

Or using the setSmooth function:

this.tag('MyObject').setSmooth('x', undefined);

Transition target value

Notice that a transition changes the property itself. If you also set a value to the same property while a transition is still running, it will be immediately overwritten by the transition before the next drawn frame. Also, getting the property value will return the current property value, and not return the property transition target value.

You can get the transition target value like this:

const targetX = this.tag('MyObject').getSmooth('x');

Fast forward

You can fast-forward the transition to the target value like this:

this.tag('MyObject').fastForward('x');

Live demo

In this demo we are going to let LilLightning compete with himself, by using three different ways of transitioning. Press right to start the transitions, or left to let him run back.

class BasicUsageExample extends lng.Application {
    static _template() {
        return {
            FinishLine:{ w: 5, h: 300, colorTop: 0xFFABABAB, colorBottom: 0xFFFFFFFF, rect: true, x: 500, y: 200 },
            LilLightningA:{ x: 50, y: 100, src: '/Lightning/img/LngDocs_LilLightningRun.png'},
            LilLightningB:{ x: 50, y: 200, src: '/Lightning/img/LngDocs_LilLightningRun.png'},
            LilLightningC:{ x: 50, y: 300, src: '/Lightning/img/LngDocs_LilLightningRun.png'}
        }
    }
    
    _handleLeft(){
        this.resetTransitions();
    }
    
    _handleRight(){
        this.startTransitions();
    }
        
    startTransitions(){
        //Face candidates to the right
        this.setCandidatesDirection('right');
        
        //Start transitions
        this.tag('LilLightningA').setSmooth('x', 500);
        this.tag('LilLightningB').setSmooth('x', 500, {duration: 2});
        this.tag('LilLightningC').patch({ smooth:{ x: [500, { duration: 2.5, delay: 1, timingFunction: 'ease-out' } ]}});
    }
    
    resetTransitions(){
        //Face candidates to the left
        this.setCandidatesDirection('left');
        
        //Start transitions
        this.tag('LilLightningA').patch({ smooth:{ x: [50, { duration: 0.5, delay: 0.2, timingFunction: 'ease-in' } ]}});
        this.tag('LilLightningB').patch({ smooth:{ x: [50, { duration: 0.5, delay: 0.4, timingFunction: 'ease-in' } ]}});
        this.tag('LilLightningC').patch({ smooth:{ x: [50, { duration: 0.5, delay: 0.6, timingFunction: 'ease-in' } ]}});
    }
    
    setCandidatesDirection(direction){
        let dir = (direction === 'left')?-1:1;
        this.tag('LilLightningA').scaleX = dir;
        this.tag('LilLightningB').scaleX = dir;
        this.tag('LilLightningC').scaleX = dir;
    }
       
}

const options = {stage: {w: window.innerWidth, h: window.innerHeight, useImageWorker: false}};
const app = new BasicUsageExample(options);
document.body.appendChild(app.stage.getCanvas());