Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix withDecay rubberBandFactor on Web #4270

Merged
merged 4 commits into from
Mar 24, 2023

Conversation

kacperkapusciak
Copy link
Member

Summary

This PR fixes an issue where rubberBandFactor on Web was handled by factor of 1000x and patch for "pixels-per-second" issue on Web for that was only applied on default config.

Before

When rubberBandEffect: true is provided a box handled with gesture shoots to the moon 馃殌

Screen.Recording.2023-03-24.at.09.56.48.mov

After

After this fix it behaves nicely 馃槑

Screen.Recording.2023-03-24.at.10.07.04.mov

Test plan

Run this snippet both in WebExample/:

import { StyleSheet, View } from 'react-native';
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withDecay,
} from 'react-native-reanimated';

import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';

export default function App() {
  const offset = useSharedValue(0);

  const pan = Gesture.Pan()
    .onChange((event) => {
      offset.value += event.changeY;
    })
    .onFinalize((event) => {
      offset.value = withDecay({
        velocity: event.velocityY,
        clamp: [-200, 200],
        rubberBandFactor: 0.7,
        rubberBandEffect: true,
      });
    });

  const animatedStyles = useAnimatedStyle(() => ({
    transform: [{ translateY: offset.value }],
  }));

  return (
    <GestureHandlerRootView style={styles.container}>
      <View style={styles.container}>
        <GestureDetector gesture={pan}>
          <Animated.View style={[styles.box, animatedStyles]} />
        </GestureDetector>
      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    height: '100%',
  },
  box: {
    height: 120,
    width: 120,
    backgroundColor: '#001A72',
    borderRadius: 20,
    cursor: 'grab',
  },
});

Copy link
Member

@piaskowyk piaskowyk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

馃憤

@kacperkapusciak kacperkapusciak added this pull request to the merge queue Mar 24, 2023
Merged via the queue into main with commit e157a21 Mar 24, 2023
@kacperkapusciak kacperkapusciak deleted the @kacperkapusciak/fix-withDecay-on-web branch March 24, 2023 09:12
kacperkapusciak added a commit that referenced this pull request May 17, 2023
## Summary

In #4270
withDecay rubberBandFactor got fixed on the Web with a fix where
velocity got multiplied by `1000` to overcome an issue present in RNGH.

This got addressed in
software-mansion/react-native-gesture-handler#2443
and released in Gesture Handler 2.10 thus making the fix unnecessary.

## Recordings

### Before with RNGH 2.10


https://github.com/software-mansion/react-native-reanimated/assets/39658211/3caf7961-3f0e-4a00-9889-18da33dbfd32

### After with RNGH 2.10


https://github.com/software-mansion/react-native-reanimated/assets/39658211/2ca02d9f-bfd6-4e13-83c2-aaa6312e8e6a


## Test plan

Run this snippet in WebExample

<details open>
<summary>Code example</summary>

```jsx
import React from 'react';
import {StyleSheet, View} from 'react-native';
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withDecay,
} from 'react-native-reanimated';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';

const SIZE = 120;

export default function App() {
  const offset = useSharedValue(0);
  const width = useSharedValue(0);

  const onLayout = event => {
    width.value = event.nativeEvent.layout.width;
  };

  const pan = Gesture.Pan()
    .onChange(event => {
      // highlight-next-line
      offset.value += event.changeX;
    })
    .onFinalize(event => {
      // highlight-start
      offset.value = withDecay({
        velocity: event.velocityX,
        rubberBandEffect: true,
        clamp: [-(width.value / 2) + SIZE / 2, width.value / 2 - SIZE / 2],
      });
      // highlight-end
    });

  const animatedStyles = useAnimatedStyle(() => ({
    transform: [{translateX: offset.value}],
  }));

  return (
    <GestureHandlerRootView style={styles.container}>
      <View onLayout={onLayout} style={styles.wrapper}>
        <GestureDetector gesture={pan}>
          <Animated.View style={[styles.box, animatedStyles]} />
        </GestureDetector>
      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    height: '100%',
  },
  wrapper: {
    flex: 1,
    width: '100%',
    alignItems: 'center',
    justifyContent: 'center',
  },
  box: {
    height: SIZE,
    width: SIZE,
    backgroundColor: '#b58df1',
    borderRadius: 20,
    cursor: 'grab',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```

</details>
fluiddot pushed a commit to wordpress-mobile/react-native-reanimated that referenced this pull request Jun 5, 2023
## Summary

This PR fixes an issue where rubberBandFactor on Web was handled by
factor of 1000x and patch for "pixels-per-second" issue on Web for that
was only applied on default config.

### Before 

When `rubberBandEffect: true` is provided a box handled with gesture
shoots to the moon 馃殌


https://user-images.githubusercontent.com/39658211/227472276-6bcec45b-75cf-4696-a5fc-34e39aae6b44.mov

### After

After this fix it behaves nicely 馃槑 




https://user-images.githubusercontent.com/39658211/227474684-cbdbecdc-e1cc-4f42-b364-94cdbac83887.mov




## Test plan
Run this snippet both in `WebExample/`:

```javascript
import { StyleSheet, View } from 'react-native';
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withDecay,
} from 'react-native-reanimated';

import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';

export default function App() {
  const offset = useSharedValue(0);

  const pan = Gesture.Pan()
    .onChange((event) => {
      offset.value += event.changeY;
    })
    .onFinalize((event) => {
      offset.value = withDecay({
        velocity: event.velocityY,
        clamp: [-200, 200],
        rubberBandFactor: 0.7,
        rubberBandEffect: true,
      });
    });

  const animatedStyles = useAnimatedStyle(() => ({
    transform: [{ translateY: offset.value }],
  }));

  return (
    <GestureHandlerRootView style={styles.container}>
      <View style={styles.container}>
        <GestureDetector gesture={pan}>
          <Animated.View style={[styles.box, animatedStyles]} />
        </GestureDetector>
      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    height: '100%',
  },
  box: {
    height: 120,
    width: 120,
    backgroundColor: '#001A72',
    borderRadius: 20,
    cursor: 'grab',
  },
});
```
fluiddot pushed a commit to wordpress-mobile/react-native-reanimated that referenced this pull request Jun 5, 2023
## Summary

In software-mansion#4270
withDecay rubberBandFactor got fixed on the Web with a fix where
velocity got multiplied by `1000` to overcome an issue present in RNGH.

This got addressed in
software-mansion/react-native-gesture-handler#2443
and released in Gesture Handler 2.10 thus making the fix unnecessary.

## Recordings

### Before with RNGH 2.10


https://github.com/software-mansion/react-native-reanimated/assets/39658211/3caf7961-3f0e-4a00-9889-18da33dbfd32

### After with RNGH 2.10


https://github.com/software-mansion/react-native-reanimated/assets/39658211/2ca02d9f-bfd6-4e13-83c2-aaa6312e8e6a


## Test plan

Run this snippet in WebExample

<details open>
<summary>Code example</summary>

```jsx
import React from 'react';
import {StyleSheet, View} from 'react-native';
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withDecay,
} from 'react-native-reanimated';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';

const SIZE = 120;

export default function App() {
  const offset = useSharedValue(0);
  const width = useSharedValue(0);

  const onLayout = event => {
    width.value = event.nativeEvent.layout.width;
  };

  const pan = Gesture.Pan()
    .onChange(event => {
      // highlight-next-line
      offset.value += event.changeX;
    })
    .onFinalize(event => {
      // highlight-start
      offset.value = withDecay({
        velocity: event.velocityX,
        rubberBandEffect: true,
        clamp: [-(width.value / 2) + SIZE / 2, width.value / 2 - SIZE / 2],
      });
      // highlight-end
    });

  const animatedStyles = useAnimatedStyle(() => ({
    transform: [{translateX: offset.value}],
  }));

  return (
    <GestureHandlerRootView style={styles.container}>
      <View onLayout={onLayout} style={styles.wrapper}>
        <GestureDetector gesture={pan}>
          <Animated.View style={[styles.box, animatedStyles]} />
        </GestureDetector>
      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    height: '100%',
  },
  wrapper: {
    flex: 1,
    width: '100%',
    alignItems: 'center',
    justifyContent: 'center',
  },
  box: {
    height: SIZE,
    width: SIZE,
    backgroundColor: '#b58df1',
    borderRadius: 20,
    cursor: 'grab',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants