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

Workshop Animations & Interactions Alicante

Workshop Animations & Interactions Alicante

Raúl Gómez Acuña

September 13, 2018
Tweet

More Decks by Raúl Gómez Acuña

Other Decks in Technology

Transcript

  1. Agenda • Everything is split into modules. We’ll cover 5

    modules in total. • Theory + hands on exercises per module • Solutions attached for reference • We’ll use expo
  2. translateX: 0 translateX: 500 progress: 0% progress: 100% translateX: 250

    progress: 50% translateX = progress * 500 translateX = 0.0 * 500 = 0 translateX = 0.5 * 500 = 250 translateX = 1.0 * 500 = 500 To define a basic computed animation, we define duration, initial position and final position. The computer takes care of animating it.
  3. Why animations are important • Animation has a special role

    in interface design, as one of the most important tools of successful interaction. • It can be said that without animation, there cannot be interaction • Users have high expectations of the UI they use, specially nowadays where the high quality content is everywhere.
  4. Animate with purpose • Don’t distract the user from successfully

    completing what they intended to do. • The best animations are those that seem natural • If you disable animations, the flow should feel broken. If it is not, this might mean your animations are superfluous
  5. Animated API • Has been designed to make it very

    easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. • Animated values bypass the usual render method, so they get updated even though there is no state change. • Animated exports four animatable component types: View, Text, Image and ScrollView.
  6. Static Drivers • There are 3 different animation types, also

    known as static drivers: timing, spring, decay • Each type provides a particular animation curve that controls how your values animate from their initial to the final value.
  7. Steps to perform animation • 1. Create animated value: const

    translateX = new Animated.Value(0); • 2. Bind the value to the Animated View (inside Render) <Animated.View style={{ transform: [{ translateX }] }} /> • 3. Run the animation with the static driver Animated.timing(translateX, { toValue: 50, duration: 1000 }).start();
  8. Exercise 1 Move a box from left to right using

    Animated timing, when the component mounts. Extra: use some elastic curve
  9. const progress = new Animated.Value(0); const scale = progress.interpolate({ inputRange:

    [0, 0.2, 0.4, 0.7, 1], outputRange: [1, 1.3, 2, 1.5, 1.2], });
  10. Interpolating to strings • Can interpolate to strings, provided that

    the string contains at least one number or is a color. • Numbers in the string are parsed and interpolated, then wrapped back in string again. • For rotation, we can use degrees or radians, i.e “360deg” or “1rad”
  11. Exercise 2 • Move a box from left to right

    • It should change opacity from 1 to 0, • It should rotate from 0 to 90 degrees when it reaches half and from 90 to 360 degrees when it reaches the end • The animation should loop over 4 times. Loop time can be 4000ms • Don’t press the button for now!
  12. Using the native driver • Rather than calling into JS

    every frame to update an animation, declare the animation configuration in JS and execute in UI thread on native. • As a consequence, JS thread can be blocked without affecting the animation. • Just add useNativeDriver: true to the animation config when starting it. Animated.timing(this.progress, { toValue: 1, duration: 1000, useNativeDriver: true // Add this line }).start();
  13. Update Native View The bridge JS Native Execute Calculate intermediate

    values useNativeDriver: true (Serialize instructions) Deserialize Instructions
  14. Update Native View The bridge JS Native Execute Calculate intermediate

    values useNativeDriver: true (Serialize instructions) Deserialize Instructions Every frame
  15. Native driver caveats • You can only animate non-layout properties

    • Things like transform and opacity will work, but flexbox and position properties will not • That’s why we were using transformX for moving the box horizontally. • Still without using native driver, animating transformX is more efficient than animating left, because with the former, the layout doesn’t have to be recalculated every frame
  16. Exercise 2 • Add useNativeDriver: true to the animation config.

    • Press the button to block the JS thread while the animation runs. • Set useNativeDriver to false and press the button again. Observe the difference
  17. Listening to value updates • It is useful sometimes to

    know what the value is at a given point in time • You can’t access the value synchronously through a public API this.progress.addListener(({ value }) => { // Do something with the value! });
  18. Exercise 3 ! • Use interpolation to transition between colours

    in the Spanish flag. • Show a text to display the current animated value in a text component. • Show an Alert when the animation finishes.
  19. Exercise 4 • Animate a button to emphasise active state,

    by scaling it up and down. The pressed state should scale it down 10% Hint: use onPressIn and onPressOut
  20. Recap • We can think of the progress of an

    animation from 0 to 1 (or any arbitrary range of numbers) • We can derive other values from the progress value with linear interpolation • Those values can be assigned to style properties on Animated Views • When the progress value updates, the interpolated values update and the views that are bound to those update • We can drive updates to the progress value using functions such as Animated.timing
  21. Value Views View Image Text ScrollView etc… subscribe to value

    updates value Driver Event driver Static driver Interpolation Number @notbrent
  22. Value Interpolation Number Views View Image Text ScrollView etc… subscribe

    to value updates value set value Driver Event driver Static driver Interpolation @notbrent
  23. Value Interpolation Number value Views View Image Text ScrollView etc…

    Driver Event driver Static driver value subscribe to Value updates subscribe to Interpolated value updates @notbrent
  24. Value Interpolation Number value Views View Image Text ScrollView etc…

    value subscribe to Value updates subscribe to Interpolated value updates set value Driver Event driver Static driver @notbrent
  25. Collapsible header • We need to define several interpolation for:

    • Toolbar —> opacity • Image —> translate • Title —> translate • Several elements with absolute position • zIndex and elevation
  26. Floating Action Button • We need to listen for scroll

    events • Animate translation: Outside and inside the screen • A bit of manual work: Save offset (Y) and compare it to the listened value to know if we scroll up or down
  27. Pan Responder It holds an InteractionManager handle to block long-running

    JS events from interrupting active gestures gestureState = { dx, dy, vx, vy, ... }
  28. Native gesture recognisers • ScrollView uses a native gesture recogniser

    instead of a JS based. • A Switch component is another example or native gesture recogniser where you can swipe or touch to flip the state • Drawer, NavigatorIOS, ViewPager…
  29. Problems 1. Gesture recognition logic is distributed between threads that

    run in parallel. 2. No API for defining interactions between native gesture recognisers, like a Drawer and a View Pager 3. Touch events recognised by JS responder system can’t be connected with Views that animate on the native thread
  30. <TapGestureHandler /> <LongPressGestureHandler /> <NativeViewGestureHandler /> <PanGestureHandler /> BEGAN ACTIVE

    FAILED CANCELLED END UNDETERMINED STATES onHandlerStateChange onGestureEvent HANDLERS
  31. Components • RN-gesture handler also offers some components that are

    built using those low level Gesture Recognisers • One of them is the <Swipeable /> component, which comes in handy in many use cases
  32. Native driver compliant <PanGestureHandler onGestureEvent={Animated.event( [ { nativeEvent: { translationX:

    this.translateX, }, }, ], { useNativeDriver: true }, )} onHandlerStateChange={this.onHandlerStateChange} >
  33. Key points • Reimplementation of Animated Module from scratch •

    It provides a more comprehensive, low level abstraction • Great flexibility for gesture based animations • Everything runs on the native thread by default!