Skip to content

Commit

Permalink
feat(📦): add approximates() and useTransition()
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Jun 23, 2019
1 parent 66e2659 commit 1077c1c
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 19 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ clamp(new Value(1), 0, 100); // 1
clamp(new Value(101), 0, 100); // 100
```

### `approximates(node, node, precision = 0.001)`

Returns 1 if the difference between the two values is less than precision.
Otherwise returns 0.
Default value for the precision is 0.001.

### `atan(node)`

Returns a arc-tangent of the value in radians of the given node.
Expand Down Expand Up @@ -235,6 +241,11 @@ contains(values: Node[], value: Node) => Node

## Animations

### `useTransition(state, source, destination, duration, easing)`

Returns an animation value that follows a Reanimated transition ([see related issue](https://github.com/kmagiera/react-native-reanimated/issues/321)).
The value equals `source` at the beginning of the transition and `destination` at the end of the transition.

### `runTiming(clock, value, config)`

Convenience function to run a timing animation.
Expand Down
47 changes: 45 additions & 2 deletions src/Animations.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import Animated from "react-native-reanimated";
import * as React from "react";
import Animated, { Easing } from "react-native-reanimated";

import { min } from "./Math";
import { runTiming } from "./AnimationRunners";

const {
Clock,
Value,
set,
add,
multiply,
cond,
eq,
abs,
sub,
interpolate,
divide
divide,
useCode
} = Animated;

export const snapPoint = (
Expand Down Expand Up @@ -43,3 +48,41 @@ export const translateZ = (
perspective: Animated.Adaptable<number>,
z: Animated.Adaptable<number>
) => ({ scale: divide(perspective, sub(perspective, z)) });

export const useTransition = (
state: any,
src: Animated.Adaptable<number>,
dest: Animated.Adaptable<number>,
duration: number = 400,
easing: Animated.EasingFunction = Easing.linear
) => {
if (!React.useMemo) {
throw new Error(
"useTransition() is only available in React Native 0.59 or higher."
);
}
if (!useCode) {
throw new Error(
"useCode() is only available in Reanimated 1.0.0 or higher"
);
}
const { transitionVal, clock } = React.useMemo(
() => ({
transitionVal: new Value(0),
clock: new Clock()
}),
[]
);
useCode(
set(
transitionVal,
runTiming(clock, src, {
toValue: dest,
duration,
easing
})
),
[state]
);
return transitionVal;
};
9 changes: 5 additions & 4 deletions src/Gesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const decay = (
export const spring = (
translation: Animated.Value<number>,
state: Animated.Value<GestureState>,
snapPoint: number,
snapPoint: Animated.Adaptable<number>,
defaultOffset: number = 0
) => {
const springedValue = new Value(0);
Expand Down Expand Up @@ -124,8 +124,8 @@ export const spring = (
export const limit = (
value: Animated.Adaptable<number>,
state: Animated.Adaptable<GestureState>,
min: number,
max: number
min: Animated.Adaptable<number>,
max: Animated.Adaptable<number>
) => {
const offset = new Animated.Value(0);
const offsetValue = add(offset, value);
Expand Down Expand Up @@ -185,5 +185,6 @@ type NativeEvent = GestureHandlerStateChangeNativeEvent &
| PinchGestureHandlerEventExtra
| ForceTouchGestureHandlerEventExtra);

export const gestureEvent = (nativeEvent: Partial<NativeEvent>) =>
type Adaptable<T> = { [P in keyof T]: Animated.Adaptable<T[P]> };
export const gestureEvent = (nativeEvent: Partial<Adaptable<NativeEvent>>) =>
event([{ nativeEvent }]);
12 changes: 9 additions & 3 deletions src/Math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ export const max = (...args: Animated.Adaptable<number>[]) =>
args.reduce((acc, arg) => max2(acc, arg));

export const clamp = (
value: Animated.Node<number>,
lowerBound: number,
upperBound: number
value: Animated.Adaptable<number>,
lowerBound: Animated.Adaptable<number>,
upperBound: Animated.Adaptable<number>
): Animated.Node<number> => min2(max2(lowerBound, value), upperBound);

export const approximates = (
a: Animated.Adaptable<number>,
b: Animated.Adaptable<number>,
precision: Animated.Adaptable<number> = 0.001
) => lessThan(abs(sub(a, b)), precision);

export const toRad = (deg: Animated.Adaptable<number>): Animated.Node<number> =>
multiply(deg, Math.PI / 180);

Expand Down
14 changes: 4 additions & 10 deletions src/bezier/CubicBezierSolve.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Animated from "react-native-reanimated";

import { find } from "../Array";
import { acos } from "../Math";
import { acos, approximates } from "../Math";

const {
Value,
Expand All @@ -10,7 +10,6 @@ const {
divide,
add,
multiply,
abs,
block,
greaterThan,
eq,
Expand All @@ -27,11 +26,6 @@ const isRootValidForCubicBezier = (root: Animated.Node<number>) =>
and(greaterThan(root, 0), lessThan(root, 1));

// pomax.github.io/bezierinfo/#extremities
const approximately = (
a: Animated.Adaptable<number>,
b: Animated.Adaptable<number>
) => lessThan(abs(sub(a, b)), 0.0001);

const cuberoot = (v: Animated.Adaptable<number>) =>
cond(
lessThan(v, 0),
Expand Down Expand Up @@ -80,10 +74,10 @@ const cubicBezierSolve = (
set(c, pa),
set(d, add(multiply(-1, pa), multiply(3, pb), multiply(-3, pc), pd)),
cond(
approximately(d, 0),
approximates(d, 0),
cond(
approximately(d, 0),
cond(not(approximately(b, 0)), set(root1, divide(multiply(-1, c), b)), [
approximates(d, 0),
cond(not(approximates(b, 0)), set(root1, divide(multiply(-1, c), b)), [
set(q, sqrt(sub(pow(b, 2), multiply(4, a, c)))),
set(root1, divide(sub(q, b), multiply(2, a))),
set(root2, divide(sub(multiply(b, -1), q), multiply(2, a)))
Expand Down

0 comments on commit 1077c1c

Please sign in to comment.