Author avatar

Vivek Kumar

ReactJS Working with Non-CSS Animations

Vivek Kumar

  • Jun 6, 2019
  • 9 Min read
  • 79 Views
  • Jun 6, 2019
  • 9 Min read
  • 79 Views
Web Development
React

Introduction

React has been a reliable source for basic animation, to date, for the novice web-project developers who would like to depict their vivid creativity on web pages via fun and cool animations.

The interface comes in multiple packages. One can see it right from react-motion and classic react transition - groups for the beginners’ honing their skills with animation to React animation, demanding much more command to fetch the desired animation results.

It is true that the world of animation has its own possibilities, especially when we try to blend live pages on the Internet. Right from the basic to the specialized CSS animation, there are so many things that could be accomplished. CSS animation enables you to attain simplicity in your work and it works pretty well with the self-contained animation. It can be easily done when you keep the state in Javascript and all the tasks related to animation on the CSS. For the animators and designers who are seeking utterly fine-grain command over their animation, the non-CSS animations with ReactJS are worth recommendation. The ReactJS can help you out with various non-CSS animations, such as paused animations or to even bring variation in the animation values in between like damping, stiffness, and acceleration.

ReactJS Limitations with the Possibilities

React Javascript can help the animators and designers with both basic and advanced animation attributes; but the interface is not free from limitations when it comes to the non-CSS animations. Here, it is essential to understand that, when it comes to the animation of SVG attributes and scroll position, the React documentation isn’t very effective.

These limitations can be well understood from the codes highlighted below. As for the transitions in CSS are concerned, there is an add-on but in the case of non-CSS transition it is not feasible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
function animate(duration, onStep) {
    var start = Date.now();
    var timer = { id: 0 };
    ( function loop() {
        timer.id = requestAnimationFrame( function() {
            var diff = Date.now() - start;
            var fraction = diff / duration;
            onStep( fraction );
            if (diff < duration) {
                loop();
            }
        } );
    } )();
    return timer;
}

function lerp( low, high, fraction ) {
    return low + ( high - low ) * fraction;
}


var App = React.createClass( {
    getInitialState: function() {
        return { x: 0 }
    },

    move: function( i ) {
        this.setState( {x: this.state.x + i * 100} );
    },

    render: function() {
        return < div className="ShowerItem" >
            <p>
                < button onClick = {this.move.bind( this, -1 )} > Left </ button>
                < button onClick = {this.move.bind( this, 1 )} > Right </ button>
            </ p>
            < svg > < Dot x = {this.state.x} /> </ svg>
        </ div>;
    }
} );


var Dot = React.createClass( {

    getInitialState: function( ) {
        return {
            x: 0,
            final: 0
        };
    },

    timer: null,

    render: function( ) {
        var from = this.state.x;
        var to = this.props.x;
        if ( to !== this.state.final ) {
            this.state.final = to;
            if ( this.timer ) {
                cancelAnimationFrame( this.timer.id );
            }

            this.timer = animate( 500, function( fraction ) {
                var x = lerp( from, to, fraction );
                if ( fraction >= 1 ) {
                    this.setState( {
                        value: to
                    } );
                    this.timer = null;
                } else {
                    this.setState( {x: x} );
                }
            }.bind( this) )
        }

        return < circle r = "10" cy = "10" cx = {this.state.x + 10} />
    }
});


React.renderComponent(
    < App />,
    document.body
);
javascript

When you go through the given code for the animation of scroll position, you will find that non-CSS animations for ReactJS have certain limitations. There are some areas where it cannot be considered the most effective way of animation. It will work in certain areas and in some areas it won’t.

The good thing is that there are certain codes that can help the animators with certain types of non-CSS animation integration like react animation and hammer events.

To help ourselves with the above code problem with animated “BlinkingThing”, one can find the successfully tested code down below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
var BlinkingThing = React.createClass( {
    mixins: [React.Animate],
    blink: function ( ) {
        var that = this;
        var animateAfter = function ( ) {
            that.animate( {
                color: 'green'
            }, that.props.blinkBack );
        };
        this.animate( {
            color: 'yellow'
        }, this.props.blinkTo, animateAfter );
    },
    componentDidReceiveProps: function ( ) {
        this.setState( { color: this.props.color } )
    },
    componentDidMount: function ( ) {
        this.setState( { color: this.props.color } )
    },
    receiveHammerEvent: function ( ev ) {
        if ( ev ) {
            var value = ev.type;

            switch ( value ) {
                case 'tap':
                    this.blink( );
                    break;
            }
        }
    },
    getInitialState: function ( ) {
        return { };
    },
    render: function ( ) {
        var style = {
            display: 'inline-block',
            backgroundColor: this.state.color
        };

        return ( < div style = { style } > { this.props.children }</ div > );
    }
});
javascript

React.Animate: Animation Mix-in Non-CSS Animations for ReactJS

Here, in order to curb this limitation with non-CSS animations, a distinct approach is suggested to animate. It is dependent on the state instead of the Document Object Model (DOM) mutation with the help of $.animate or any identical type of code performing the same function.

The Document Object Model showcases the document in the form of a logic tree which helps in the formation and use of refs after the completion of a render. One of the key benefits of applying react is that there can always be an observable, straight, and testable relationship among the component props, the state as well as the rendered output.

Now, what is interesting here is that bringing the direct mutation in the DOM can generate an anti-pattern. Here, what we actually wish to animate is not the Document Object Model, but rather its component state.

If you actually believe that animation is basically a transition from one particular state value to another, then it would be easier for you to interpolate the state over a specific interval. Henceforth, your component could render accurately in exchange with the present component state at each step.

It is arguably the easiest. React.Animate permits you to transition from one specific state to another in a set period of time. The application of the code leads to the identical syntax which is $.animate.

1
2
3
this.animate( properties [, duration ] [, easing ] [, complete ] );
or
this.animate( key, value [, duration ] [, easing ] [, complete ] );

An Illustration

It is possible to incorporate React.Animate to any sort of React class by including it in the mixins array.

By substituting the DOM directly, by animating the state, we can actually display logic during specific phases of our animations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var component = React.createClass( {
  mixins: [React.Animate],
  getInitialState: function( ) {
    return {
      width: 100
    };
  },
  render: function( ) {
    var heightBounds = [50, 100];

    return React.DOM.div( {
      style: {
        width: this.state.width,
        height: Math.min( heightBounds[ 1 ], Math.max( heightBounds[ 0 ], this.state.width / 2) )
      },
      onClick: this.randomSize
    });
  },
  randomSize: function( ) {
    this.animate( {
      width: _.random( 20, 300 )
    }, 500, function( ) {
      console.log( "random size reached!" );
    });
  }
});
javascript

Conclusion

Is the provided code architecture correct? Well, as any standard coder would say, there is no denying that there is always room for improvement. When new suggestions as well as schemes, or other things evolve in the future, one can find that the limitations associated with non-CSS animations for ReactJS can be transformed into possibilities with the passage of time.

0