简体   繁体   中英

React native animation loop hooks

I have to make the loops spin.

So I have degree = 0 which must gradually reach degree = 360, and then start from 0 and return to 360 and so on.

I tried this way but it's not working, where am I doing wrong?

 const grado = React.useRef(new Animated.Value(0)).current;

  React.useEffect(() => {
    /*Animated.loop(
      Animated.timing(grado, {
        toValue: 1,
        duration: 300,
        easing: Easing.linear,
      })
    ).start();*/

    Animated.loop(
      Animated.spring(grado, {
        toValue: 1,
        friction: 1,
      }),
      { iterations: 1000 }
    ).start();
  }, []);

  const spinT = grado.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 360],
  });

Link: snack

import React, { useState } from 'react';
import { StyleSheet, View, Animated, Text, Easing } from 'react-native';
import Svg, { Circle, G } from 'react-native-svg';
const AnimatedCircle = Animated.createAnimatedComponent(Circle);

export default ({
  image,
  width,
  height,
  innerCircle = false,
  innerCircleRadius = 13,
  innerCircleFillPercentage = 25,
  innerCircleStroke = '#143c5b',
  innerCircleStrokeAnimated = '#02ac8a',
  outerCircle = false,
  outerCircleRadius = 18,
  outerCircleFillPercentage = 50,
  outerCircleStroke = '#1f4a42',
  outerCircleStrokeAnimated = '#028cfe',
  degree,
}) => {
  const innerCirclePerimeter = 2 * Math.PI * innerCircleRadius;
  const innerCircleStrokeDashOffset =
    innerCirclePerimeter -
    (innerCirclePerimeter * innerCircleFillPercentage) / 100;

  const outerCirclePerimeter = 2 * Math.PI * outerCircleRadius;
  const outerCircleStrokeDashOffset =
    outerCirclePerimeter -
    (outerCirclePerimeter * outerCircleFillPercentage) / 100;

  const [springValue] = useState(new Animated.Value(1.3));

  const [innerCircleInitialFill] = useState(
    new Animated.Value(innerCirclePerimeter)
  );
  const [outerCircleInitialFill] = useState(
    new Animated.Value(outerCirclePerimeter)
  );

  React.useEffect(() => {
    Animated.parallel([
      Animated.timing(innerCircleInitialFill, {
        toValue: innerCircleStrokeDashOffset,
        duration: 1000,
      }),
      Animated.timing(outerCircleInitialFill, {
        toValue: outerCircleStrokeDashOffset,
        duration: 2000,
      }),
      Animated.spring(springValue, {
        toValue: 1,
        friction: 1,
      }),
    ]).start();
  }, [
    innerCircleInitialFill,
    outerCircleInitialFill,
    springValue,
    innerCircleStrokeDashOffset,
    outerCircleStrokeDashOffset,
  ]);

  const outer = () => {
    return (
      outerCircle && (
        <>
          <Circle
            cx="25"
            cy="25"
            r={outerCircleRadius}
            fill="transparent"
            stroke={outerCircleStroke}
            strokeDasharray="10, 1"
            strokeDashoffset="30"
            strokeWidth={0.5}
          />
          <AnimatedCircle
            cx="25"
            cy="25"
            r={outerCircleRadius}
            fill="transparent"
            stroke={innerCircleStrokeAnimated}
            strokeDasharray={outerCirclePerimeter}
            strokeDashoffset={outerCircleInitialFill}
            strokeLinecap={'round'}
          />
        </>
      )
    );
  };

  const inner = () => {
    return (
      innerCircle && (
        <>
          <Circle
            cx="25"
            cy="25"
            r={innerCircleRadius}
            fill="transparent"
            stroke={innerCircleStroke}
            strokeDasharray="1"
            strokeWidth={0.5}
          />
          <AnimatedCircle
            cx="25"
            cy="25"
            r={innerCircleRadius}
            fill="transparent"
            stroke={outerCircleStrokeAnimated}
            strokeDasharray={innerCirclePerimeter}
            strokeDashoffset={innerCircleInitialFill}
            strokeLinecap={'round'}
          />
        </>
      )
    );
  };

  const Image = () => (
    <View
      style={{
        position: 'absolute',
        justifyContent: 'center',
        alignItems: 'center',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
      }}>
      <Animated.Image
        source={image}
        style={[
          styles.image,
          {
            width,
            height,
            borderRadius: width * 0.5,
            transform: [{ scale: springValue }],
          },
        ]}
      />
    </View>
  );

  //console.log(degree, height * Math.cos(degree), width * Math.sin(degree));

  const grado = React.useRef(new Animated.Value(0)).current;

  React.useEffect(() => {
    /*Animated.loop(
      Animated.timing(grado, {
        toValue: 1,
        duration: 300,
        easing: Easing.linear,
      })
    ).start();*/

    Animated.loop(
      Animated.spring(grado, {
        toValue: 1,
        friction: 1,
      }),
      { iterations: 1000 }
    ).start();
  }, []);

  const spinT = grado.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 360],
  });

  console.log('c', grado, spinT);
  const spin = 45;

  return (
    <View
      style={[
        styles.container,
        {
          //width: width * 1.5,
          //height: height * 1.5,
          //borderRadius: 2 * Math.PI * outerCircleRadius,
          backgroundColor: '#cccccca1',
        },
      ]}>
      <View>
        <Svg
          viewBox={`0 0 50 50`}
          width={width * 2.5}
          height={height * 2.5}
          style={{
            transform: [{ rotateZ: '-90deg' }],
          }}>
          <G>
            {outer()}
            {inner()}
          </G>
        </Svg>
        {Image()}

        <Text
          style={{
            fontSize: width * 0.12,
            fontWeight: 'bold',
            color: '#ffffff',

            position: 'absolute',
            justifyContent: 'center',
            alignItems: 'center',
            textAlign: 'center',

            display: 'flex',

            top:
              height -
              height * Math.cos((spinT * Math.PI) / 180) +
              (height * 0.2) / 2,
            left:
              width +
              width * Math.sin((spinT * Math.PI) / 180) +
              (width * 0.2) / 2,
            backgroundColor: '#1393DB',
            borderRadius: 10,
            width: width * 0.2,
            height: height * 0.2,
            shadowColor: '#000',
            shadowOffset: {
              width: 0,
              height: 2,
            },
            shadowOpacity: 0.25,
            shadowRadius: 3.84,
            elevation: 5,
          }}>
          21
        </Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    alignItems: 'center',
    //backgroundColor: 'rgba(168, 152, 50, 0.5)',
  },
});

Just add the loop before the parallel function.

Animated.loop(
      Animated.parallel([
        Animated.timing(innerCircleInitialFill, {
          toValue: innerCircleStrokeDashOffset,
          duration: 1000,
        }),
        Animated.timing(outerCircleInitialFill, {
          toValue: outerCircleStrokeDashOffset,
          duration: 2000,
        }),
        Animated.spring(springValue, {
          toValue: 1,
          friction: 1,
        }),
      ]),
      {
        iterations: 10,
      }
    ).start();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM