React-Native animations has some limitations on what can be done using the native driver and what can only be executed in the Javascript realm. Animating colors is an example of property you can only animate using the JS interpreter, which is super slow and will probably affect your performance. If you try and hang a few interpolates in that Animated.Value, you’ll have a bad time trying to have fluid and seemless animations.

If only there was a way of using one Animated.Value to drive another Animated.Value

thinking gif

💡 What if you use a native animation’s listener to drive a non-native animation?

Yes, that’s possible. No, using a listener doesn’t automatically make your animation non-native. This means you’ll need multiple Animated.Values (if that wasn’t clear yet):

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
const nativeAnim = new Animated.Value(0); // 1
const jsAnim = new Animated.Value(0);

// component did mount
useEffect(() => {
  // this is the trick: drive the non-native animation by adding a listener to the native animation
  const nativeListener = nativeAnim.addListener(Animated.event([{ value: jsAnim }])); // 3
  return () => {
    nativeAnim.removeListener(nativeListener);
  };
}, []);

// backgroundColor can only be animated using a non-native animation
const bgColorStyle = jsAnim.interpolate({ // 4
  inputRange: [0, 100],
  outputRange: ['red', 'black'],
});

// using the native driver still works
const positionStyle = {
  transform: [{
    translateX: this.nativeAnim.interpolate({
      inputRange: [0, 2],
      outputRange: [0, 1],
    }),
  }],
};

...

<ScrollView
  onScroll={
    Animated.event([{
      nativeEvent: {
        contentOffset: { x: nativeAnim }, // 2
      },
    }, { useNativeDriver: true }])
  } // 🎉
/>

Let’s recap what’s up there:

  1. We defined nativeAnim and jsAnim, which are Animated.Value.
  2. This value is driven by a native Animated.event triggered by a ScrollView’s offset.
  3. We added a listener to nativeAnim to drive a second Animated.Value, by using a non-native Animated.event.
  4. The non-native animation (jsAnim) is then used to animate a backgroundColor, which is a style property that can only be animated by non-native animations.

That truly works, check it out:

Rogue Bit 🕹

I have a peculiar taste in video games. I’ve never been an avid gamer despite owning consoles andbuilding a gaming PC when I was younger. …… Continue reading

The Art of Coding

Published on September 26, 2019

Hooking Your Hooks

Published on August 28, 2019