React Native自定义动画会降低应用程序的速度

时间:2018-04-19 10:05:23

标签: react-native

我试图将一个脉冲动画添加到一个按钮,然后按照插件https://github.com/sahlhoff/react-native-pulse中的代码构建一个。生成的组件如下所示:

import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    left: 0,
    right: 0,
    alignItems: 'center'
  },
  pulse: {
    position: 'absolute',
    flex: 1
  }
});

export default class Pulse extends Component {
  static defaultProps = {
    style: {
      top: 0,
      bottom: 0,
      flexDirection: 'row',
      justifyContent: 'center',
      alignItems: 'center'
    },
    color: 'blue',
    numPulses: 3,
    diameter: 400,
    speed: 10,
    duration: 1000
  };

  constructor(props) {
    super(props);

    this.state = {
      started: false,
      style: this.props.style,
      image: this.props.image,
      color: this.props.color,
      numPulses: this.props.numPulses,
      maxDiameter: this.props.diameter,
      speed: this.props.speed,
      duration: this.props.duration,
      pulses: []
    };
  }

  componentDidMount() {
    const { numPulses, duration, speed } = this.state;

    this.starter();

    let a = 0;
    while (a < numPulses) {
      this.createPulseTimer = setTimeout(() => {
        this.createPulse(a);
      }, a * duration);

      a++;
    }

    this.timer = setInterval(() => {
      this.updatePulse();
    }, speed);
  }

  componentWillUnmount() {
    this.mounted = false;
    clearTimeout(this.createPulseTimer);
    clearInterval(this.timer);
  }

  mounted = true;

  createPulse = () => {
    if (this.mounted) {
      const { pulses } = this.state;

      const pulse = {
        pulseKey: pulses.length + 1,
        diameter: 0,
        opacity: 0.5
      };

      pulses.push(pulse);

      this.setState({ pulses });
    }
  };

  starter() {
    this.setState({ started: true });
  }

  updatePulse = () => {
    if (this.mounted) {
      const pulses = this.state.pulses.map((p, i) => {
        const { maxDiameter } = this.state;
        const newDiameter = p.diameter > maxDiameter ? 0 : p.diameter + 2;
        const centerOffset = (maxDiameter - newDiameter) / 2;
        const opacity = Math.abs(newDiameter / this.state.maxDiameter - 1);

        const pulse = {
          pulseKey: i + 1,
          diameter: newDiameter,
          opacity: opacity > 0.5 ? 0.5 : opacity,
          centerOffset
        };

        return pulse;
      });

      this.setState({ pulses });
    }
  };

  render() {
    const {
      style, image, maxDiameter, color, started, pulses
    } = this.state;
    const wrapperStyle = [styles.container, style];
    const containerStyle = { width: maxDiameter, height: maxDiameter };

    return (
      <View style={wrapperStyle}>
        {started && (
          <View style={containerStyle}>
            {pulses.map(pulse => (
              <View
                key={pulse.pulseKey}
                style={[
                  styles.pulse,
                  {
                    backgroundColor: color,
                    width: pulse.diameter,
                    height: pulse.diameter,
                    opacity: pulse.opacity,
                    borderRadius: pulse.diameter / 2,
                    top: pulse.centerOffset,
                    left: pulse.centerOffset
                  }
                ]}
              />
            ))}
            {this.props.children}
          </View>
        )}
      </View>
    );
  }
}

问题是,这会大大减慢应用程序的速度。通常,应用程序以大约60fps(UI和JS)运行。但是当这个组件处于活动状态时,JS性能下降到接近35fps。知道发生了什么事吗?该应用在Android上运行。

1 个答案:

答案 0 :(得分:0)

考虑使用Animated API。它快得多。 可以使用缩放动画轻松创建脉冲。