react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
80 lines (73 loc) • 3.05 kB
JavaScript
import { defineAnimation, getReduceMotionForAnimation } from './util';
// TODO TYPESCRIPT This is a temporary type to get rid of .d.ts file.
export const withRepeat = function (_nextAnimation) {
'worklet';
let numberOfReps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
let reverse = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
let callback = arguments.length > 3 ? arguments[3] : undefined;
let reduceMotion = arguments.length > 4 ? arguments[4] : undefined;
return defineAnimation(_nextAnimation, () => {
'worklet';
const nextAnimation = typeof _nextAnimation === 'function' ? _nextAnimation() : _nextAnimation;
function repeat(animation, now) {
const finished = nextAnimation.onFrame(nextAnimation, now);
animation.current = nextAnimation.current;
if (finished) {
animation.reps += 1;
// call inner animation's callback on every repetition
// as the second argument the animation's current value is passed
if (nextAnimation.callback) {
nextAnimation.callback(true /* finished */, animation.current);
}
if (animation.reduceMotion || numberOfReps > 0 && animation.reps >= numberOfReps) {
return true;
}
const startValue = reverse ? nextAnimation.current : animation.startValue;
if (reverse) {
nextAnimation.toValue = animation.startValue;
animation.startValue = startValue;
}
nextAnimation.onStart(nextAnimation, startValue, now, nextAnimation.previousAnimation);
return false;
}
return false;
}
const repCallback = finished => {
if (callback) {
callback(finished);
}
// when cancelled call inner animation's callback
if (!finished && nextAnimation.callback) {
nextAnimation.callback(false /* finished */);
}
};
function onStart(animation, value, now, previousAnimation) {
animation.startValue = value;
animation.reps = 0;
// child animations inherit the setting, unless they already have it defined
// they will have it defined only if the user used the `reduceMotion` prop
if (nextAnimation.reduceMotion === undefined) {
nextAnimation.reduceMotion = animation.reduceMotion;
}
// don't start the animation if reduced motion is enabled and
// the animation would end at its starting point
if (animation.reduceMotion && reverse && (numberOfReps <= 0 || numberOfReps % 2 === 0)) {
animation.current = animation.startValue;
animation.onFrame = () => true;
} else {
nextAnimation.onStart(nextAnimation, value, now, previousAnimation);
}
}
return {
isHigherOrder: true,
onFrame: repeat,
onStart,
reps: 0,
current: nextAnimation.current,
callback: repCallback,
startValue: 0,
reduceMotion: getReduceMotionForAnimation(reduceMotion)
};
});
};
//# sourceMappingURL=repeat.js.map