UNPKG

3.39 kBPlain TextView Raw
1'use strict';
2import type { AnimationObject, Mutable } from './commonTypes';
3
4export function valueSetter<Value>(
5 mutable: Mutable<Value>,
6 value: Value,
7 forceUpdate = false
8): void {
9 'worklet';
10 const previousAnimation = mutable._animation;
11 if (previousAnimation) {
12 previousAnimation.cancelled = true;
13 mutable._animation = null;
14 }
15 if (
16 typeof value === 'function' ||
17 (value !== null &&
18 typeof value === 'object' &&
19 // TODO TYPESCRIPT fix this after fixing AnimationObject type
20 (value as unknown as AnimationObject).onFrame !== undefined)
21 ) {
22 const animation: AnimationObject<Value> =
23 typeof value === 'function'
24 ? // TODO TYPESCRIPT fix this after fixing AnimationObject type
25 (value as () => AnimationObject<Value>)()
26 : // TODO TYPESCRIPT fix this after fixing AnimationObject type
27 (value as unknown as AnimationObject<Value>);
28 // prevent setting again to the same value
29 // and triggering the mappers that treat this value as an input
30 // this happens when the animation's target value(stored in animation.current until animation.onStart is called) is set to the same value as a current one(this._value)
31 // built in animations that are not higher order(withTiming, withSpring) hold target value in .current
32 if (
33 mutable._value === animation.current &&
34 !animation.isHigherOrder &&
35 !forceUpdate
36 ) {
37 animation.callback && animation.callback(true);
38 return;
39 }
40 // animated set
41 const initializeAnimation = (timestamp: number) => {
42 animation.onStart(animation, mutable.value, timestamp, previousAnimation);
43 };
44 const currentTimestamp =
45 global.__frameTimestamp || global._getAnimationTimestamp();
46 initializeAnimation(currentTimestamp);
47
48 const step = (newTimestamp: number) => {
49 // Function `requestAnimationFrame` adds callback to an array, all the callbacks are flushed with function `__flushAnimationFrame`
50 // Usually we flush them inside function `nativeRequestAnimationFrame` and then the given timestamp is the timestamp of end of the current frame.
51 // However function `__flushAnimationFrame` may also be called inside `registerEventHandler` - then we get actual timestamp which is earlier than the end of the frame.
52
53 const timestamp =
54 newTimestamp < (animation.timestamp || 0)
55 ? animation.timestamp
56 : newTimestamp;
57
58 if (animation.cancelled) {
59 animation.callback && animation.callback(false /* finished */);
60 return;
61 }
62 const finished = animation.onFrame(animation, timestamp);
63 animation.finished = true;
64 animation.timestamp = timestamp;
65 // TODO TYPESCRIPT
66 // For now I'll assume that `animation.current` is always defined
67 // but actually need to dive into animations to understand it
68 mutable._value = animation.current!;
69 if (finished) {
70 animation.callback && animation.callback(true /* finished */);
71 } else {
72 requestAnimationFrame(step);
73 }
74 };
75
76 mutable._animation = animation;
77
78 step(currentTimestamp);
79 } else {
80 // prevent setting again to the same value
81 // and triggering the mappers that treat this value as an input
82 if (mutable._value === value && !forceUpdate) {
83 return;
84 }
85 mutable._value = value;
86 }
87}