Перейти к содержанию

withRepeat

withRepeat - это модификатор анимации, позволяющий повторять анимацию заданное количество раз или запускать ее бесконечно.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import React from 'react';
import Animated, {
    Easing,
    useAnimatedStyle,
    useSharedValue,
    withRepeat,
    withTiming,
} from 'react-native-reanimated';
import { StyleSheet, View } from 'react-native';

const duration = 2000;
const easing = Easing.bezier(0.25, -0.5, 0.25, 1);

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

    React.useEffect(() => {
        // highlight-next-line
        sv.value = withRepeat(
            withTiming(1, { duration, easing }),
            -1
        );
    }, []);

    const animatedStyle = useAnimatedStyle(() => ({
        transform: [{ rotate: `${sv.value * 360}deg` }],
    }));

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

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

Описаие

1
2
3
4
5
6
import { withRepeat } from 'react-native-reanimated';

function App() {
    sv.value = withRepeat(withSpring(0), 5);
    // ...
}

Типизация

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type AnimatableValue = number | string | number[];

function withRepeat<T extends AnimatableValue>(
    animation: T,
    numberOfReps?: number,
    reverse?: boolean,
    callback?: (
        finished?: boolean,
        current?: AnimatableValue
    ) => void
): T;

Аргументы

animation

Анимация, которую вы хотите повторить.

numberOfReps

Количество повторов анимации. По умолчанию равно 2.

Неположительное значение (например, 0 или -1) приведет к тому, что анимация будет повторяться бесконечно, пока не будет отменена или снесена. Например, если компонент размонтирован или была вызвана функция cancelAnimation.

reverse

Должна ли анимация запускаться в обратном направлении при каждом втором повторении. По умолчанию имеет значение false.

Эта опция поддерживает только функции анимации (например, withSpring) и не работает с модификаторами анимации (например, withSequence).

callback

Функция, вызываемая по завершении анимации. В случае отмены анимации обратный вызов получит в качестве аргумента false, в противном случае - true.

Возвращает

withRepeat возвращает объект анимации. Он может быть либо напрямую присвоен shared value, либо использован в качестве значения для объекта стиля, возвращаемого из useAnimatedStyle.

Пример

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import React from 'react';
import { View, Button, StyleSheet } from 'react-native';
import Animated, {
    useSharedValue,
    withTiming,
    Easing,
    useAnimatedStyle,
    withRepeat,
    withSequence,
} from 'react-native-reanimated';

const ANGLE = 10;
const TIME = 100;
const EASING = Easing.elastic(1.5);

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

    const animatedStyle = useAnimatedStyle(() => ({
        transform: [{ rotateZ: `${rotation.value}deg` }],
    }));

    const handlePress = () => {
        // highlight-next-line
        rotation.value = withSequence(
            // deviate left to start from -ANGLE
            withTiming(-ANGLE, {
                duration: TIME / 2,
                easing: EASING,
            }),
            // wobble between -ANGLE and ANGLE 7 times
            withRepeat(
                withTiming(ANGLE, {
                    duration: TIME,
                    easing: EASING,
                }),
                7,
                true
            ),
            // go back to 0 at the end
            withTiming(0, {
                duration: TIME / 2,
                easing: EASING,
            })
            // highlight-next-line
        );
    };

    return (
        <View style={styles.container}>
            <Animated.View
                style={[styles.box, animatedStyle]}
            />
            <Button title="wobble" onPress={handlePress} />
        </View>
    );
}

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

Замечания

  • Обратный вызов, переданный в 4-м аргументе, автоматически workletized и запускается на UI thread.

Совместимость с платформами

Android iOS Web

Ссылки

Комментарии