software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.86k stars 1.29k forks source link

V2: interpolateNode causes crash #875

Closed sa8ab closed 4 years ago

sa8ab commented 4 years ago

Description

when using interpolateNode the app crashes

Steps To Reproduce

  1. create an interpolateNode value and assign it to useAnimatedStyle
const width = interpolateNode(tY.value, {
    inputRange: [10, 100],
    outputRange: [40, 200],
    Extrapolate: Extrapolate.CLAMP,
  });

Reanimated 2

jakub-gonet commented 4 years ago

You're mixing Reanimated 1 and reanimated 2, right? This may be not supported when you're using nodes in new hooks

sa8ab commented 4 years ago

No the tY in the example is equal to useSharedValue().

Can you provide an example of using interpolation in v2 please?

terrysahaidak commented 4 years ago
const width = interpolate(
    tY.value,
    [10, 100],
    [40, 200],
    Extrapolate.CLAMP,
);
sa8ab commented 4 years ago

No luck @terrysahaidak

I tried the following

const width = interpolateNode(tY.value, {
    inputRange: [0, 100],
    outputRange: [10, 200],
    Extrapolate: Extrapolate.CLAMP,
  });

also

const width = interpolate(tY.value, {
    inputRange: [0, 100],
    outputRange: [10, 200],
    Extrapolate: Extrapolate.CLAMP,
  });

and when using any of them in the useAnimatedStyle or direclty in the style of the component, it crashes, result of console.log of for the one you sent me (interpolate, not intepolateNode) was NaN, also console logging the result of interpolateNode causes crash

terrysahaidak commented 4 years ago

Please, carefully read my suggestion. The interpolation in Reanimated2 takes 4 parameters: sharedValue's value, array of input, array of output and extrapolate. You're using 2 parameters instead and passing the object as a second one. That's how interpolate node works

sa8ab commented 4 years ago

Thank you @terrysahaidak , sorry my bad didn't notice the change, Currently I do the following and I don't see any update in the interpolated value

const width = interpolate(tY.value, [10, 100], [40, 200], Extrapolate.CLAMP);

here is the log: image

terrysahaidak commented 4 years ago

Could you post a code snipped with those logs and useAnimatedStyle?

sa8ab commented 4 years ago

Yes, sure. @terrysahaidak here you go.

import React from 'react';
import {StyleSheet, View, Text} from 'react-native';
import Animated, {
  withSpring,
  useSharedValue,
  useAnimatedStyle,
  useAnimatedGestureHandler,
  interpolate,
  Extrapolate,
} from 'react-native-reanimated';
import {PanGestureHandler} from 'react-native-gesture-handler';

const App = () => {
  const tY = useSharedValue(0);
  const width = interpolate(tY.value, [10, 100], [40, 200], Extrapolate.CLAMP);
  const gestureEvent = useAnimatedGestureHandler({
    onStart: (event, context) => {
      context.start_tY = tY.value;
    },
    onActive: (event, context) => {
      tY.value = event.translationY;

      console.log('tY.value', tY.value);
      console.log('width', width);
    },
    onEnd: () => {
      tY.value = withSpring(0);
    },
  });

  const sz = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateY: tY.value,
        },
      ],
    };
  });
  return (
    <View>
      <Text>hello</Text>
      <Animated.View style={{...s.pan2, width}} />
      <PanGestureHandler onGestureEvent={gestureEvent}>
        <Animated.View style={[s.pan, sz]} />
      </PanGestureHandler>
    </View>
  );
};

const s = StyleSheet.create({
  pan: {
    width: 80,
    height: 80,
    backgroundColor: 'teal',
  },
  pan2: {
    height: 80,
    backgroundColor: 'gray',
  },
});

export default App;
terrysahaidak commented 4 years ago

The interpolate function in Reanimated2 is a pure function. It takes arguments and returns a value.

You have two options here:

  1. Use and log interpolate inside the worklet (useAnimatedStyle or inside any of the gesture handlers)
  2. Wrap that interpolate call with useDerivedValue - it returns a shared value, so make sure to use .value:
const width = useDerivedValue(() => {
  return interpolate(...);
});
sa8ab commented 4 years ago

Works perfectly now thanks alot @terrysahaidak, :)

I used the derivedValue also had to use useAnimatedStyle to make it work.

sa8ab commented 4 years ago

just wonder why first syntax does not work and we need to use the second one image

terrysahaidak commented 4 years ago

useAnimatedStyle body is being executed on the UI Thread. When you pass its result (styles) to Animated.View as style, it bounds that style to that view and tells "if something changes in the AnimatesStyles, please update the view".

Since you can return different styles at any time from useAnimatedStyle, you cannot just "spread" it.

Also, you can no longer pass animated values (now they are shared values) as style properties directly.

sa8ab commented 4 years ago

@terrysahaidak Great explanation. What about clamping only left or only right? do they go as 5th and 6th parameters??

terrysahaidak commented 4 years ago

Seems like these are missing right now. Could you open a new issue for this?

sa8ab commented 4 years ago

@terrysahaidak indeed I will open a new one, what about color interpolations, is it possible in v2?

terrysahaidak commented 4 years ago

It is. Check out the first example in the example app.

sa8ab commented 4 years ago

@terrysahaidak I noticed it is basically using a value for HSL color, I wonder if it is possible like the "interpolateColors" from reanimated v1;

https://docs.swmansion.com/react-native-reanimated/docs/1.x.x/nodes/interpolateColors

terrysahaidak commented 4 years ago

What is your use case? Do you want to be able to interpolate separately r/g/b?

sa8ab commented 4 years ago

@terrysahaidak Asking to see if I am able to do like the following

interpolateColors( //or interpolate()
   someValue.value, 
   [1, 100],
   [ 'red' , 'gold' ] //or HEX values
   Extrapolate.CLAMP
)
terrysahaidak commented 4 years ago

I believe @Szymon20000 has wrote some color interpolation logic already.

sa8ab commented 4 years ago

@terrysahaidak Will we have it on next updated?

terrysahaidak commented 4 years ago

@wcandillon has more context on this

M2Changezi commented 3 years ago

@terrysahaidak As documentation says that interpolate named to interpolateNode so how does reanimted 2 and up versions are accepting interpolate

M2Changezi commented 3 years ago

@terrysahaidak May u suggest any better explanation ,blog , etc of the reanimted 2 hooks under the hood

terrysahaidak commented 3 years ago

With Reanimated 2 interpolate accepts some value instead of animated node, and then two arrays - input range and output range. The last parameter is options.

You can take a look at example here:

https://github.com/software-mansion/react-native-reanimated/blob/master/Example/src/ExtrapolationExample.tsx#L46

M2Changezi commented 3 years ago

@terrysahaidak ok how about this question !

@terrysahaidak As documentation says that interpolate named to interpolateNode so how does reanimted 2 and up versions are accepting interpolate

terrysahaidak commented 3 years ago

@terrysahaidak ok how about this question !

@terrysahaidak As documentation says that interpolate named to interpolateNode so how does reanimted 2 and up versions are accepting interpolate

If you are using reanimated v1 then interpolate renamed to interpolateNode. If you want to use interpolation in V2 you can just import "interpolate" because now it's a worklet.

You can learn about worklet in documentation and this video

M2Changezi commented 3 years ago

@terrysahaidak thanku Sir that helped me alot

M2Changezi commented 3 years ago

@terrysahaidak how can we debug , watch in , or inspect the code of reanimated 2 (hooks ,etc)

shadahmad7 commented 2 years ago

Go to drawer.js file in /node_modules/react-navigation-drawer/lib/module/views/ and change interpolate to interpolatenode on two places. your problem solved

chris-mactavis commented 2 years ago

Go to drawer.js file in /node_modules/react-navigation-drawer/lib/module/views/ and change interpolate to interpolatenode on two places. your problem solved

This works for me, thanks

prayaslashkari commented 2 years ago

Diffclamp is not working. @terrysahaidak any idea? How can we make it work.