first_gif.gif

We built a new game on Quizlet called Gravity to help students learn vocabulary while having fun. As words fall down your screen from outer space in the form of "asteroids," you race to type the answer before they hit the planet.

Building all the animations we needed in React gave us an opportunity to push the boundaries of what it can do.

React is still relatively new, and it wasn’t created to support animations — its declarative nature and under-the-hood DOM updating system do not provide us with time-based control over our UI. However, we felt that the benefits of using React outweighed the limitations [1], and we were willing to place a bet that the awesome community around React would help us fill in the gaps—and they did.

Different animations in the game had different requirements, and were supported by different approaches: for asteroids falling we used react-tween-state, for planet advancement VelocityJS, and for the level-up badge, CSS keyframes. This post is about how and why we built each animation the way we did.

Animation I: Asteroids falling downwards

Y4i6LH.gif

The Need:

Animate a single dimension of an element, with the ability to control timing and start & stop the animation at will.

The Solution:

React-tween-state: a simple library that updates a given property of an element over the course of a period of time by updating the state. In the author’s words: “The equivalent of React's this.setState, but for animated tweens: this.tweenState.”

We declared the asteroid’s fall via three values: a start value, end value, and duration. We could also pause the fall on demand by grabbing the asteroid’s current position and setting that to be the new start and end values. This API gave us full control over the asteroid’s position over time while also making it simple to animate continuously without user input.

Alternatives:

React-motion is a more advanced library that allows you to animate components using spring physics. While our linear-timed animation may not accurately represent the physics of an asteroid falling through space, it is well-suited for a student trying to learn a vocabulary word (imagine how stressful the game would be if the asteroids accelerated!) Although react-motion is newer and more extensible, react-tween-state is smaller and provides all the functionality we need, so we chose the simpler library.

Animation II: A planet zooming in from afar

FqdzK1.gif

The Need:

Animate the position and size of 3 images simultaneously, between two game states. On any screen size, the bottom planet should be centered while the next two planets are in the top right corner.

The Solution:

Velocity-react: a React wrapper for the Velocity.JS DOM animation library, which provides the power of CSS animations in JavaScript.

Since viewport dimensions are only accessible via Javascript, it was natural to calculate other dimensions in Javascript as well. React’s inline styles made it easy to apply these styles and Velocity allowed us to transform them in a performant way. Incidentally, the APIs for inline styles and Velocity animations are similar (just pass in key-value pairs of CSS properties!) so this made the code pretty nice and readable, too.

Since there were no user interactions involved with this animation, we could have also implemented it entirely in CSS, using transform and translate. Without information about the viewport dimensions from CSS, however, we could only size and position the planets using percentages. In that case, we would have to translate the planets using percentages as well. However, when you use percentages with CSS’s translate, the percentages are applied to the element being translated rather than the parent—this just would have involved a bit of extra math to get the desired effect. We tried applying CSS transitions to the top and left properties but that turned out to have terrible performance compared to CSS transform.

Animation III: A badge zooming/fading in and out

9GPL8q.gif

The Need:

Animate scale and opacity of an image in the middle of another animation

The Solution:

CSS3 keyframes. Since the badge is always the same size and we always want it to zoom in and out after a fixed delay, CSS animations were enough to get the job done. We attached an is-levelingUp class during the level-up state and added a 500ms delay to give the planets a head start.

Alternatives

We tried using ReactCSSTransitionGroup to animate the badge in and out of the DOM:

The outcome of this was inconsistent—the animation was sometimes fast-forwarded or cut off. Fine-grained timing was not in our control. Turns out CSSTransitionGroup is good for transitioning in or out of the DOM, but not in and out of the DOM. We then realized there was no need to actually remove the badge from the DOM—we could just render it with 0 opacity when we didn’t want to show it.

Another option was using VelocityJS, which allows you to specify the timing of multiple components in parallel with its UI Pack plugins. If we had used Velocity, all the timing would be in one place and we wouldn’t run the risk of CSS and Javascript animations interfering with each other or being timed incorrectly. The downside is that we would break modularity by having the component’s animation controlled by another component, perhaps some central animation coordinator. Ultimately, we decided it was okay if the badge and planet synchronization had a small margin of error and when we tested it across browsers, it actually appeared to be fairly consistent. Coordinating the animation of multiple components via Velocity is something worth exploring further, though.

Conclusion

There is currently no single, clear-cut way to implement animations in React; rather there are many ways to animate components depending on your needs. As React and these supporting libraries continue to develop, we’ve found that experimenting with different options (and remembering to test across browsers!) is the best way to find something that works. In the future, perhaps animations in React will become more streamlined. In the meantime, we are thankful to the developer community for creating all these solutions thus far and excited to see what further developments arise down the road.

In what ways have you animated components in React? Do you have suggestions for other ways to implement the animations I described? Tweet @jenkliu. And if building animations to make learning more fun for millions of people is something that interests you, let me know—we’re hiring!


[1] We've enjoyed using ReactJS on previous projects with its declarative nature, modularity, performance, and overall collaboration-friendliness.

Comments

  1. sjagrosenberg

    5th comment and high five!

  2. tjn6

    sixth comment and 6th high five

  3. tjn6

    personal best

  4. Username_Unknown11

    seventh high five personal best :-)

  5. silvershadow777

    9th comment

  6. samonellafella

    You should try out his class! We are committed to studying harder.

  7. jc_da_boss3

    JC_da_boss score on quizlet space race is higher than 4 billion!! Try to compete!

  8. Sup_Homie

    Plus that GIF says Hawaii on it! Thats where I'm from!

  9. Sup_Homie

    What a small world this is!

  10. Animated_Boyie

    Son Goku is my man fools!

  11. jc_da_boss2

    I LOVE QUIZLET, YOU SHOULD TOO!

  12. Rhombicosidodecahdon

    Longest name ever! LOL

  13. Rhombicosidodecahdon

    Why can't i stop saying that?

  14. MOO_HOO

    SO TRU ^
    I
    I
    I

  15. MOO_HOO

    Ur name is sure long!

  16. AmandaIp1

    It's a great game, and it's really helpful! Space race is helpful too, but I like how Gravity has words going "down" your screen.

  17. Mako_Chris

    Quizlet actually works really well for me, especially Gravity lol. I now know all my terms by heart, no matter the class.

  18. Mako_Chris

    Problem with the game though is that it comes to a point where it doesn't matter how well you know the terms, but it soon becomes based on how fast you type. Although, I suppose you wouldn't even get to that part of the game if you weren't a good typer in the first place. Fortunately, this isn't a problem for me as I am a good typer, not to brag. I actually have come to find it a new challenge and to improve my typing speed WHILE learning! Fantastic!

  19. heartsophia

    awesome game!!!!!!!!!!!!!!!!!!23th comment

  20. lucy94103

    Me, I personally liked space race better, although there were no animations. But the background is simple. 24th high five!! personal best for high fives!!! 2nd best for leaving a comment

  21. lucy94103

    oh but the person above me says she's 23rd comment. I was 24 at first so now I'm 25!!!! I don't think this post was viewed buy lots of people. Almost nobody commented on this post. I wonder why...

  22. Nicholas_Sedlock

    Hi
    17th
    some people commented more then one time so i'm really 17th
    anyway who cares I don't have android 

  23. maddiestigman

    Cool! 20th person to comment. But honestly Apple trumps Android anyday

  24. Nicholas_Sedlock

    ◊◊◊◊

  25. monsterdecookie

    nobody cares that you are the first high five or comment

  26. MaDe-Of-StArS

    @Mako_

    Same here

  27. FCBAYERNMUCHEN

    WHo 31st Person to comment best day of my life

  28. HANEEN_KURDI

    same as 1rst comment

  29. Josiah_May_

    Wayyyyy cool! :)

  30. Josiah_May_

    47th high five!!!

  31. hi_sick

    SPACE RACE
    NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

  32. hi_sick

    no high five
    :(

  33. susan_lee_elliott

    38 th comment

  34. tp103

    Cool Game!

  35. radioactiveion

    he he he funny

  36. katiecat100

    Just LUV this game😍 helps me study & it fun and easy ! XD ✌️❤️

  37. Lovecamaro

    This new game or upgrade is actually pretty cool.👍👍👍👍👍

  38. Lovecamaro

    67th high five!✋✋✋✋✋✋✋✋✋

  39. Luke_Chase

    cool! loved this post cause I understood like 99% of it! just wondering, would https://github.com/ai/easings.net have worked?

  40. MTowlgirl

    Wow! I am very interested in react and hope to learn more ;D

  41. Zachary_Zehring

    Cool, already know about it!

  42. tp103

    how do you make a game like that so easily? is there any lessons to learn how to code it.

  43. maracello

    I love quizlet

Leave a comment

Login to leave a comment