Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Moving Beyond Animations to User Interactions at 60 FPS

Tal Kol
March 13, 2017

Moving Beyond Animations to User Interactions at 60 FPS

* Given in ReactConf 2017 in Santa Clara on March 13, 2017

The async nature of the React Native bridge incurs an inherent performance penalty. This traditionally prevented JavaScript code to run at high framerates. The most noticeable challenge is animations in JS, which aren't guaranteed to run at 60 FPS.

Modern animation libraries for React Native, like Animated, tackle this challenge with a declarative approach. In order to minimize passes over the bridge, animations are declared in JS but executed by a native driver on the other side.

User interactions are a step further than animations. Interactions require UI to continuously react to the user's gestures. Consider a drawer opening with buttons appearing gradually as it is being dragged, or a card being swiped away. Unfortunately, those are still lagging behind.

We'll demonstrate JS implementations for complex interactions that run at 60 FPS. We'll also demonstrate how to generalize this approach with a library. Similar to Animated - just aimed at interactions, not animations.

Tal Kol

March 13, 2017
Tweet

More Decks by Tal Kol

Other Decks in Programming

Transcript

  1. Moving Beyond Animations to User Interactions at 60 FPS PUSHING

    BOUNDARIES WITH REACT NATIVE TAL KOL Head of Mobile Engineering at Wix.com |
  2. What makes great apps? THE MAGICAL NUANCES THAT SET YOU

    APART Fluid animations at 60 FPS Dynamic user interactions that mimic reality
  3. Implement in native? ONE SURE WAY TO REDUCE BRIDGE TRAFFIC

    That's what we do in our app (as OSS) Native skillset is required, the 10% rule
  4. Learn from animations § Similar problem JS animations are noisy

    over the bridge § Animated library emerged as the way to deal with this § Declarative API to specify the behavior in JS at once § JS/native driver takes the declaration and runs frame by frame
  5. ListView Row Actions 1 x = 0 x = 100

    horizontal: true snapPoints: [ {x: 0}, {x: 100} ] friction: 0.7
  6. Swipeable Cards 2 x = -360 x = 0 horizontal:

    true snapPoints: [ {x: -360} {x: 0}, {x: 360} ] friction: 0.6
  7. Collapsible Views 3 y = 250 y = 0 vertical:

    true snapPoints: [ {y: 0}, {y: 250} ] friction: 0.8
  8. Sliding Panels & Drawers 4 y = 0 vertical: true

    snapPoints: [ {y: 0}, {y: 660} ] friction: 0.5 y = 660
  9. TouchEvent(x1) UpdateView Frame 1 TouchEvent(x2) Frame 2 JavaScript Native Bridge

    Initialize Declare Interaction Initialize Driver UpdateView
  10. Drag with gesture recognizer then animate using spring to closest

    snap point Implement native driver – phase 1
  11. Compute the entire interaction with UIKit Dynamics – a full

    fledged iOS physics engine Implement native driver – phase 2
  12. Physics 101 NEWTON TO THE RESCUE ∆ = 2 −

    1 = − ( ∆ = ∆ = ( ∆
  13. Switch to our own custom physics engine for more control

    and ability to port to Android Implement native driver – phase 3
  14. Enrich API – 3 § animate other views (Animated) d

    = new Animated.Value(0) animatedValueX: d
  15. Enrich API – 4 snapPoints: [ {x: -140}, {x: 140}

    ] gravityPoints: [ {x: 0, y: 200, strength: 8000} ] friction: 0.8 animatedValueY: this.deltaY onStop: this.onStopEvent haptics: true