0

react-native の Animated を使用して、react コンポーネントを React-Native に移植しようとしています。

私は円を作成することができました。それは軌道であり、うまく機能しています。

しかし、react-native の Animated でそれらのルールを記述する方法がわかりません。

アニメーションの@keyframes fulfilling-bouncing-circle-spinner-orbit-animation半分まで待つ必要があります。その後、縮小と拡大を 2 回行う必要があります。

で、@keyframes fulfilling-bouncing-circle-spinner-circle-animation反応ネイティブ アニメーションを使用してスタイルを追加および削除する方法がわからないので、考え続けましたが、アイデアが思い浮かびませんでした。

時系列を追加し、@keyframes と同じようにそれらのフレームで必要なことを行う方法はありますか。

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const BouncingCircle = styled.div`
  height: ${props => props.size}px;
  width: ${props => props.size}px;
  position: relative;
  animation: fulfilling-bouncing-circle-spinner-animation infinite
    ${props => props.animationDuration}ms ease;
  * {
    box-sizing: border-box;
  }
  .orbit {
    height: ${props => props.size}px;
    width: ${props => props.size}px;
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 50%;
    border: calc(${props => props.size}px * 0.03) solid ${props => props.color};
    animation: fulfilling-bouncing-circle-spinner-orbit-animation infinite
      ${props => props.animationDuration}ms ease;
  }
  .circle {
    height: ${props => props.size}px;
    width: ${props => props.size}px;
    color: ${props => props.color};
    display: block;
    border-radius: 50%;
    position: relative;
    border: calc(${props => props.size}px * 0.1) solid ${props => props.color};
    animation: fulfilling-bouncing-circle-spinner-circle-animation infinite
      ${props => props.animationDuration}ms ease;
    transform: rotate(0deg) scale(1);
  }
  @keyframes fulfilling-bouncing-circle-spinner-animation {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
  @keyframes fulfilling-bouncing-circle-spinner-orbit-animation {
    0% {
      transform: scale(1);
    }
    50% {
      transform: scale(1);
    }
    62.5% {
      transform: scale(0.8);
    }
    75% {
      transform: scale(1);
    }
    87.5% {
      transform: scale(0.8);
    }
    100% {
      transform: scale(1);
    }
  }
  @keyframes fulfilling-bouncing-circle-spinner-circle-animation {
    0% {
      transform: scale(1);
      border-color: transparent;
      border-top-color: inherit;
    }
    16.7% {
      border-color: transparent;
      border-top-color: initial;
      border-right-color: initial;
    }
    33.4% {
      border-color: transparent;
      border-top-color: inherit;
      border-right-color: inherit;
      border-bottom-color: inherit;
    }
    50% {
      border-color: inherit;
      transform: scale(1);
    }
    62.5% {
      border-color: inherit;
      transform: scale(1.4);
    }
    75% {
      border-color: inherit;
      transform: scale(1);
      opacity: 1;
    }
    87.5% {
      border-color: inherit;
      transform: scale(1.4);
    }
    100% {
      border-color: transparent;
      border-top-color: inherit;
      transform: scale(1);
    }
  }
`;

const propTypes = {
  size: PropTypes.number,
  animationDuration: PropTypes.number,
  color: PropTypes.string,
  className: PropTypes.string,
  style: PropTypes.object,
};

const defaultProps = {
  size: 60,
  color: '#fff',
  animationDuration: 4000,
  className: '',
};

const FulfillingBouncingCircleSpinner = ({
  size,
  color,
  animationDuration,
  className,
  style,
  ...props
}) => (
  <BouncingCircle
    size={size}
    color={color}
    animationDuration={animationDuration}
    className={`fulfilling-bouncing-circle-spinner${
      className ? ' ' + className : ''
    }`}
    style={style}
    {...props}
  >
    <div className="circle" />
    <div className="orbit" />
  </BouncingCircle>
);

FulfillingBouncingCircleSpinner.propTypes = propTypes;
FulfillingBouncingCircleSpinner.defaultProps = defaultProps;

export default FulfillingBouncingCircleSpinner;
/** @flow **/
import React, { useEffect, useState } from 'react';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import { Animated, Easing, StyleSheet } from 'react-native';
import { AnimationUtils } from '../animationUtils';

type EpicProps = {
  size?: number,
  duration?: number,
  color?: string,
  style?: ViewStyleProp
};

const EpicDefaultProps = {
  size: 200,
  color: 'red',
  duration: 1000
};

export const FulfillingBouncingCircleSpinner = ({ size, color, duration, style, ...props }: EpicProps) => {
  const [animate] = useState(new Animated.Value(0));
  const spinnerStyle = StyleSheet.create({
    container: {
      height: size,
      width: size,
      position: 'relative'
    },
    circle: {
      height: size,
      width: size,
      borderColor: color,
      borderRadius: size * 0.5,
      position: 'relative',
      borderWidth: size * 0.1
    },
    orbit: {
      height: size,
      width: size,
      position: 'absolute',
      top: 0,
      left: 0,
      borderColor: color,
      borderRadius: size * 0.5,
      borderWidth: size * 0.03
    }
  });

  const containerRotation = AnimationUtils.interpolation(animate, [0, 1], ['0deg', '360deg']);
  const circle = AnimationUtils.interpolation(animate, [0, 1], [1, 1.4]);
  const orbit = AnimationUtils.interpolation(animate, [0, 1], [1, 0.8]);

  useEffect(() => {
    Animated.loop(
      Animated.sequence([
        Animated.timing(animate, { toValue: 1, duration: duration, useNativeDriver: true, easing: Easing.back() }),
        Animated.timing(animate, { toValue: 0, duration: duration, useNativeDriver: true, easing: Easing.back() })
      ])
    ).start();
  }, [animate, duration]);

  return (
    <Animated.View style={[style, spinnerStyle.container, { transform: [{ rotate: containerRotation }] }]} {...props}>
      <Animated.View style={[spinnerStyle.circle, { transform: [{ scaleX: circle }, { scaleY: circle }] }]} />
      <Animated.View style={[spinnerStyle.orbit, { transform: [{ scaleX: orbit }, { scaleY: orbit }] }]} />
    </Animated.View>
  );
};

FulfillingBouncingCircleSpinner.defaultProps = EpicDefaultProps;
4

1 に答える 1