Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import DoubleDraggable from './release_tests/doubleDraggable';
import { ComboWithGHScroll } from './release_tests/combo';
import { TouchablesIndex, TouchableExample } from './release_tests/touchables';
import Rows from './release_tests/rows';
import Fling from './release_tests/fling';
import NestedFling from './release_tests/nestedFling';
import MouseButtons from './release_tests/mouseButtons';
import ContextMenu from './release_tests/contextMenu';
import NestedTouchables from './release_tests/nestedTouchables';
Expand All @@ -34,6 +34,7 @@ import PanResponder from './basic/panResponder';
import HorizontalDrawer from './basic/horizontalDrawer';
import PagerAndDrawer from './basic/pagerAndDrawer';
import ForceTouch from './basic/forcetouch';
import Fling from './basic/fling';

import ReanimatedSimple from './new_api/reanimated';
import Camera from './new_api/camera';
Expand Down Expand Up @@ -77,6 +78,7 @@ const EXAMPLES: ExamplesSection[] = [
{ name: 'Horizontal drawer', component: HorizontalDrawer },
{ name: 'Pager & drawer', component: PagerAndDrawer },
{ name: 'Force touch', component: ForceTouch },
{ name: 'Fling', component: Fling },
],
},
{
Expand Down Expand Up @@ -116,7 +118,7 @@ const EXAMPLES: ExamplesSection[] = [
{ name: 'Double pinch & rotate', component: DoublePinchRotate },
{ name: 'Double draggable', component: DoubleDraggable },
{ name: 'Rows', component: Rows },
{ name: 'Fling', component: Fling },
{ name: 'Nested Fling', component: NestedFling },
{ name: 'Combo', component: ComboWithGHScroll },
{ name: 'Touchables', component: TouchablesIndex as React.ComponentType },
{ name: 'MouseButtons', component: MouseButtons },
Expand Down
57 changes: 57 additions & 0 deletions example/src/basic/fling/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import {
Directions,
Gesture,
GestureDetector,
} from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
Easing,
} from 'react-native-reanimated';

export default function Example() {
const position = useSharedValue(0);
const beginPosition = useSharedValue(0);

const flingGesture = Gesture.Fling()
.direction(Directions.LEFT | Directions.RIGHT)
.onBegin((e) => {
beginPosition.value = e.x;
})
.onStart((e) => {
const direction = Math.sign(e.x - beginPosition.value);
position.value = withTiming(position.value + direction * 50, {
duration: 300,
easing: Easing.bounce,
});
});

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

return (
<View style={styles.centerView}>
<GestureDetector gesture={flingGesture}>
<Animated.View style={[styles.box, animatedStyle]} />
</GestureDetector>
</View>
);
}

const styles = StyleSheet.create({
centerView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
box: {
height: 120,
width: 120,
backgroundColor: '#b58df1',
marginBottom: 30,
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { USE_NATIVE_DRIVER } from '../../config';
const windowWidth = Dimensions.get('window').width;
const circleRadius = 30;

class Fling extends Component {
class NestedFling extends Component {
private touchX: Animated.Value;
private translateX: Animated.AnimatedAddition<number>;
private translateY: Animated.Value;
Expand Down Expand Up @@ -88,7 +88,7 @@ export default class Example extends Component {
render() {
return (
<View>
<Fling />
<NestedFling />
<Text>
Move up (with two fingers) or right/left (with one finger) and watch
magic happens
Expand Down
17 changes: 13 additions & 4 deletions src/Directions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
const RIGHT = 1;
const LEFT = 2;
const UP = 4;
const DOWN = 8;

export const Directions = {
RIGHT: 1,
LEFT: 2,
UP: 4,
DOWN: 8,
RIGHT: RIGHT,
LEFT: LEFT,
UP: UP,
DOWN: DOWN,
UP_RIGHT: UP | RIGHT,
DOWN_RIGHT: DOWN | RIGHT,
UP_LEFT: UP | LEFT,
DOWN_LEFT: DOWN | LEFT,
} as const;

// eslint-disable-next-line @typescript-eslint/no-redeclare -- backward compatibility; it can be used as a type and as a value
Expand Down
26 changes: 20 additions & 6 deletions src/web/handlers/FlingGestureHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Vector from '../tools/Vector';

const DEFAULT_MAX_DURATION_MS = 800;
const DEFAULT_MIN_VELOCITY = 700;
const DEFAULT_MIN_DIRECTION_ALIGNMENT = 0.75;
const DEFAULT_DIRECTIONAL_ALIGNMENT_CONE = 40;
const DEFAULT_DIRECTION = Directions.RIGHT;
const DEFAULT_NUMBER_OF_TOUCHES_REQUIRED = 1;

Expand All @@ -17,14 +17,23 @@ export default class FlingGestureHandler extends GestureHandler {

private maxDurationMs = DEFAULT_MAX_DURATION_MS;
private minVelocity = DEFAULT_MIN_VELOCITY;
private minDirectionalAlignment = DEFAULT_MIN_DIRECTION_ALIGNMENT;
private directionalAlignmentCone = DEFAULT_DIRECTIONAL_ALIGNMENT_CONE;
private delayTimeout!: number;

private maxNumberOfPointersSimultaneously = 0;
private keyPointer = NaN;

private minimalAlignmentCosine = 0;

public init(ref: number, propsRef: React.RefObject<unknown>): void {
super.init(ref, propsRef);

const degToRad = (degrees: number) => (degrees * Math.PI) / 180;

const alignmentRadians = degToRad(this.directionalAlignmentCone);
const maxDirectionalDeviation = alignmentRadians / 2;

this.minimalAlignmentCosine = Math.cos(maxDirectionalDeviation);
}

public updateGestureConfig({ enabled = true, ...props }: Config): void {
Expand All @@ -50,18 +59,23 @@ export default class FlingGestureHandler extends GestureHandler {
private tryEndFling(): boolean {
const velocityVector = Vector.fromVelocity(this.tracker, this.keyPointer);

const getAlignment = (direction: Directions) => {
const getAlignment = (
direction: Directions,
minimalAlignmentCosine: number
) => {
return (
direction & this.direction &&
(direction & this.direction) === direction &&
velocityVector.isSimilar(
Vector.fromDirection(direction),
this.minDirectionalAlignment
minimalAlignmentCosine
)
);
};

// list of alignments to all activated directions
const alignmentList = Object.values(Directions).map(getAlignment);
const alignmentList = Object.values(Directions).map((direction) =>
getAlignment(direction, this.minimalAlignmentCosine)
);

const isAligned = alignmentList.some(Boolean);
const isFast = velocityVector.magnitude > this.minVelocity;
Expand Down
5 changes: 5 additions & 0 deletions src/web/tools/Vector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ const DirectionToVectorMappings = new Map<Directions, Vector>([
[Directions.RIGHT, new Vector(1, 0)],
[Directions.UP, new Vector(0, -1)],
[Directions.DOWN, new Vector(0, 1)],

[Directions.UP_RIGHT, new Vector(1, -1)],
[Directions.DOWN_RIGHT, new Vector(1, 1)],
[Directions.UP_LEFT, new Vector(-1, -1)],
[Directions.DOWN_LEFT, new Vector(-1, 1)],
]);