React native 反应本机svg心脏大小动画

React native 反应本机svg心脏大小动画,react-native,animation,svg,expo,react-animated,React Native,Animation,Svg,Expo,React Animated,我正在尝试使用svg图像在ReactNative expo中制作一个脉动的svg心脏 我唯一能够使心脏使用动画值调整大小的方法是将其绑定到style:fontSize 这似乎可以正确地更改大小,但动画确实不稳定 代码如下: import React, { Component } from 'react'; import { Animated } from 'react-native'; import { SimpleLineIcons } from '@expo/vector-icons';

我正在尝试使用svg图像在ReactNative expo中制作一个脉动的svg心脏

我唯一能够使心脏使用动画值调整大小的方法是将其绑定到style:fontSize

这似乎可以正确地更改大小,但动画确实不稳定

代码如下:

import React, { Component } from 'react';
import { Animated } from 'react-native';
import { SimpleLineIcons } from '@expo/vector-icons';

const AnimatedIcon = Animated.createAnimatedComponent(SimpleLineIcons);

const TARGET_FONT_SIZE = 16;
const GROWN_FONT_SIZE = 24;

class GrowingHeart extends Component<any, any> {
  size = new Animated.Value(TARGET_FONT_SIZE);

  constructor(props) {
    super(props);

    Animated.sequence([
      Animated.timing(this.size, {
        duration: 1000,
        toValue: GROWN_FONT_SIZE
      }),

      Animated.timing(this.size, {
        duration: 1000,
        toValue: GROWN_FONT_SIZE
      })
    ]).start();
  }
  render() {
    return (
      <AnimatedIcon
        style={{ fontSize: this.size }}
        size={20}
        name="heart"
        color="red"
      />
    );
  }
}
import React,{Component}来自'React';
从“react native”导入{Animated};
从“@expo/vector icons”导入{SimpleLineIcons};
const AnimatedIcon=Animated.createAnimatedComponent(SimpleLineIcons);
常量目标字体大小=16;
const-GROWN\u-FONT\u-SIZE=24;
类GrowingHeart扩展组件{
大小=新的动画值(目标字体大小);
建造师(道具){
超级(道具);
动画序列([
动画。计时(此尺寸{
持续时间:1000,
toValue:字体大小
}),
动画。计时(此尺寸{
持续时间:1000,
toValue:字体大小
})
]).start();
}
render(){
返回(
);
}
}
我也试着绑定宽度和高度,但它们也是起伏的+它们改变容器大小,而不是图标


有更好的方法吗?谢谢

看来动画api还是垃圾(如果我弄错了,请纠正我)

我用reanimated重新写了这篇文章,效果很好。下面的代码并不完整,但显示了心脏是如何生长的,没有起伏,而是非常平滑

import React, { Component } from 'react';
import { TouchableOpacity } from 'react-native-gesture-handler';
import Animated, { Easing } from 'react-native-reanimated';
import { SimpleLineIcons } from '@expo/vector-icons';

const {
  createAnimatedComponent,
  debug,
  set,
  get,
  block,
  eq,
  Value,
  cond,
  greaterThan,
  startClock,
  timing,
  Clock,
  Code,
  clockRunning,
  stopClock
} = Animated;

const AnimatedIcon = createAnimatedComponent(SimpleLineIcons);

const TARGET_FONT_SIZE = 16;
const GROWN_FONT_SIZE = 20;

class GrowingHeart extends Component<any, any> {
  size = new Value(TARGET_FONT_SIZE);
  clock = new Clock();
  updatingValue = new Value(0);

  clockState = {
    finished: new Value(0),
    position: new Value(5),
    time: new Value(0),
    frameTime: new Value(0)
  };

  clockConfig = {
    duration: new Value(500),
    toValue: new Value(GROWN_FONT_SIZE),
    easing: Easing.linear
  };

  constructor(props) {
    super(props);
  }

  render() {
    const { color } = this.props;
    const { updatingValue, size, clock, clockConfig, clockState } = this;

    return (
      <>
        <Code>
          {() =>
            block([
              cond(
                // animation not triggered
                eq(0, updatingValue),
                [],
                [
                  cond(
                    clockRunning(clock),
                    [],
                    [
                      set(clockState.finished, 0),
                      set(clockState.time, 0),
                      set(clockState.position, TARGET_FONT_SIZE),
                      set(clockState.frameTime, 0),
                      set(clockConfig.toValue, GROWN_FONT_SIZE),
                      startClock(clock)
                    ]
                  ),
                  cond(
                    greaterThan(0, updatingValue),
                    // is decreasing
                    [debug('going down', updatingValue)],
                    // is growing
                    [
                      timing(clock, clockState, clockConfig),
                      set(size, clockState.position)
                    ]
                  ),
                  cond(clockState.finished, [stopClock(clock)])
                ]
              )
            ])
          }
        </Code>
        <TouchableOpacity
          onPress={() => {
            this.updatingValue.setValue(1);
          }}
        >
          <AnimatedIcon
            style={{ fontSize: this.size }}
            name="heart"
            color={color}
          />
        </TouchableOpacity>
      </>
    );
  }
}

似乎动画api仍然是垃圾(如果我弄错了,请纠正我)

我用reanimated重新写了这篇文章,效果很好。下面的代码并不完整,但显示了心脏是如何生长的,没有起伏,而是非常平滑

import React, { Component } from 'react';
import { TouchableOpacity } from 'react-native-gesture-handler';
import Animated, { Easing } from 'react-native-reanimated';
import { SimpleLineIcons } from '@expo/vector-icons';

const {
  createAnimatedComponent,
  debug,
  set,
  get,
  block,
  eq,
  Value,
  cond,
  greaterThan,
  startClock,
  timing,
  Clock,
  Code,
  clockRunning,
  stopClock
} = Animated;

const AnimatedIcon = createAnimatedComponent(SimpleLineIcons);

const TARGET_FONT_SIZE = 16;
const GROWN_FONT_SIZE = 20;

class GrowingHeart extends Component<any, any> {
  size = new Value(TARGET_FONT_SIZE);
  clock = new Clock();
  updatingValue = new Value(0);

  clockState = {
    finished: new Value(0),
    position: new Value(5),
    time: new Value(0),
    frameTime: new Value(0)
  };

  clockConfig = {
    duration: new Value(500),
    toValue: new Value(GROWN_FONT_SIZE),
    easing: Easing.linear
  };

  constructor(props) {
    super(props);
  }

  render() {
    const { color } = this.props;
    const { updatingValue, size, clock, clockConfig, clockState } = this;

    return (
      <>
        <Code>
          {() =>
            block([
              cond(
                // animation not triggered
                eq(0, updatingValue),
                [],
                [
                  cond(
                    clockRunning(clock),
                    [],
                    [
                      set(clockState.finished, 0),
                      set(clockState.time, 0),
                      set(clockState.position, TARGET_FONT_SIZE),
                      set(clockState.frameTime, 0),
                      set(clockConfig.toValue, GROWN_FONT_SIZE),
                      startClock(clock)
                    ]
                  ),
                  cond(
                    greaterThan(0, updatingValue),
                    // is decreasing
                    [debug('going down', updatingValue)],
                    // is growing
                    [
                      timing(clock, clockState, clockConfig),
                      set(size, clockState.position)
                    ]
                  ),
                  cond(clockState.finished, [stopClock(clock)])
                ]
              )
            ])
          }
        </Code>
        <TouchableOpacity
          onPress={() => {
            this.updatingValue.setValue(1);
          }}
        >
          <AnimatedIcon
            style={{ fontSize: this.size }}
            name="heart"
            color={color}
          />
        </TouchableOpacity>
      </>
    );
  }
}

您是否尝试过使用lottie而不是svg?因为rn没有为svgI提供很多选择,但svgI还没有。我正在尝试尽可能地使用原始解决方案您是否尝试过使用lottie而不是svg?因为rn没有为svgI提供很多选择,但svgI还没有。我尽量用原液