Romy
Romy

Reputation: 407

function-like interpolation in React Native?

I have a scrollview with fixed length in my RN project that should act like a parralax scroll behavior. When I scroll and move the Y component, the X component of the header is moving right so when it is on top, it is 56 pixels away from the left edge, leaving enough place for the back arrow.

But it is linear. Is there a way to make it exponential. The best example would be the WhatsApp contact's parralax scroll:

Watch the Title "Dune"

enter image description here

How I have it now = red line (linear)

How I would like to = blue line (linear with easing, exponential, whatever it's called)

I got the scaling animation done, but the linear motion is like a thorn in my eye and the documentation for Animated values is overwhelming and unclear a bit.

I've defined:

scrollY: new Animated.Value(0)

in state and in my scrollview like this:

   <ScrollView
      onScroll={Animated.event(
        [{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
      )}

and my Animated.View inside of it looks like this:

      <Animated.View  
        style={[
          {marginTop: 30, alignSelf: 'flex-start' },
          {translateX: headerTranslateX}
        ]}]}>
        <Text>Title</Text>
      </Animated.View>

Aand the interpolation:

const titleTranslateX = this.state.scrollY.interpolate({
  inputRange: [0, HEADER_SCROLL_DISTANCE*0.6, HEADER_SCROLL_DISTANCE],
  outputRange: [0, 0, 56],
  extrapolate: 'clamp',
})

which is linear in nature (i tried setting 10+keypoints in inputRange and outputRange bit but it gets messy and doesn't look natural enough)

Any advice on how to achieve the desired effect?

Upvotes: 5

Views: 4888

Answers (1)

duhseekoh
duhseekoh

Reputation: 1363

The only thing it says in the Animated docs on easing (function interpolation) is:

Interpolation

Each property can be run through an interpolation first. An interpolation maps input ranges to output ranges, typically using a linear interpolation but also supports easing functions. By default, it will extrapolate the curve beyond the ranges given, but you can also have it clamp the output value.

It doesn't mention how you can add an easing function. However, in the source code you'll find this: https://github.com/facebook/react-native/blob/e2ce98b7c6f4f2fc7011c214f9edc1301ff30572/Libraries/Animated/src/Interpolation.js#L27

export type InterpolationConfigType = {
  inputRange: Array<number>,
  /* $FlowFixMe(>=0.38.0 site=react_native_fb,react_native_oss) - Flow error
   * detected during the deployment of v0.38.0. To see the error, remove this
   * comment and run flow
   */
  outputRange: (Array<number> | Array<string>),
  easing?: ((input: number) => number),
  extrapolate?: ExtrapolateType,
  extrapolateLeft?: ExtrapolateType,
  extrapolateRight?: ExtrapolateType,
};

The easing function defaults to linear (t) => t, but you can make it any standard easing function. Here's a nice list: https://gist.github.com/gre/1650294

Note: this won't work if you're using useNativeDriver: true.

Hope this helps reduce the choppiness!

Upvotes: 6

Related Questions