动画 - 如何通过插值将动画值转换为实际值

时间:2017-01-14 05:18:28

标签: animation react-native

我试图同时限制动画的值(使用钳位和插值),但也从插值中获取值,以便我可以使用它们。特别是因为我想用它们更新一个状态并从中创建一个observable。我无法弄清楚如何提取真实的'由插值产生的AnimatedValue的值(在本例中为state.panValue)。我试过了

this.state.panValue.value 

this.state.panValue._value 

他们回来时未定义。如果有人能帮助我,那将是惊人的!

编辑:我也很高兴能够拥有

this.state.pan.x

变量在限制范围内更新,因此我可以跳过整个更新状态变量' panValue'事情。 Facebook上的一个好人建议我可以通过将变量切换为函数或其他东西在onPanResponderMove中以某种方式实现此限制但我已经尝试了几件事而我得到的都是错误,我猜是因为我不是真的知道如何安全地#39;修改这些动画值。

      onPanResponderMove: Animated.event([
      null,
      { dx: this.state.pan.x },
    ]),

原始代码:

import React, { Component } from 'react';
import {
  View,
  Animated,
  PanResponder,
  Text,
} from 'react-native';
import styles from './styles';

class ClockInSwitch extends Component {
  constructor(props) {
   super(props);
   this.state = {
   pan: new Animated.ValueXY(),
   panValue: 0,
  };
 }

componentWillMount() {
 this._animatedValueX = 0;
 this._animatedValueY = 0;
 this.state.pan.x.addListener((value) => {
   this._animatedValueX = value.value;
    this.setState({
        panValue: this.state.pan.x.interpolate({
          inputRange: [-30, 0, 120,],
          outputRange: [-10, 0, 120,],
          extrapolate: 'clamp',
        }),
    });
});

this._panResponder = PanResponder.create({
  // Ask to be the responder:
  onStartShouldSetPanResponder: (evt, gestureState) => true,
  onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
  onMoveShouldSetPanResponder: (evt, gestureState) => true,
  onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

  onPanResponderGrant: (evt, gestureState) => {
    this.state.pan.setOffset({
      x: this._animatedValueX,
    });
    this.state.pan.setValue({ x: 0, y: 0 });
  },
  onPanResponderMove: Animated.event([
      null,
      { dx: this.state.pan.x },
    ]),
  onPanResponderTerminationRequest: (evt, gestureState) => true,
  onPanResponderRelease: (evt, gestureState) => {
    this.state.pan.flattenOffset();
    Animated.timing(this.state.pan, {
      toValue: 0,
      duration: 500,
    }).start();
  },
  onPanResponderTerminate: (evt, gestureState) => {
  },
  onShouldBlockNativeResponder: (evt, gestureState) => {
    return true;
  },
 });
}

componentWillUnMount() {
  this.state.pan.x.removeAllListeners();
}

render() {
   const animatedStyle = {
    transform: [{
    translateX: this.state.panValue,
    },
    ],
  };
return (
  <View>
    <Text>{this.state.pan.x._value}</Text>
    <View style={styles.buttonStyle}>
      <Animated.View
        style={[styles.sliderButtonStyle, animatedStyle]}
        {...this._panResponder.panHandlers}
      />
    </View>
  </View>
   );
  }
}

export default ClockInSwitch;

1 个答案:

答案 0 :(得分:2)

我认为这是你正在寻找的东西。我使用exponent,因此您可能需要更改矢量图标的声明。干杯!

&#13;
&#13;
/**
 * @providesModule ClockInSwitch
 * @flow
 */
import React, {Component} from 'react';
import {View, Animated, StyleSheet, PanResponder, Text} from 'react-native';
import {FontAwesome} from '@exponent/vector-icons';

export class ClockInSwitch extends Component {
    constructor(props) {
        super(props);
        this.state = {
            pan: new Animated.ValueXY(),
            panValue: 0
        };
    }
    componentWillMount() {
        this._panResponder = PanResponder.create({
            onMoveShouldSetResponderCapture: () => true,
            onMoveShouldSetPanResponderCapture: () => true,
            onPanResponderGrant: (e, gestureState) => {
                this
                    .state
                    .pan
                    .setValue({x: 0, y: 0});
            },
            //here's where you can check, constrain and store values
            onPanResponderMove: (evt, gestureState) => {
                // 300 is the width of the red container (will leave it to you to calculate this
                // dynamically) 100 is the width of the button (90) plus the 5px margin on
                // either side of it (10px total)
                var newXVal = (gestureState.dx < 300 - 100)
                    ? gestureState.dx
                    : 300 - 100;
                this
                    .state
                    .pan
                    .x
                    .setValue(newXVal);
                //set this state for display
                this.setState({panValue: newXVal});
            },

            onPanResponderRelease: (e, {vx, vy}) => {
                this
                    .state
                    .pan
                    .flattenOffset();
                Animated
                    .spring(this.state.pan, {
                    toValue: 0,
                    duration: 400,
                    overshootClamping: true
                })
                    .start();
                this.setState({panValue: 0});
            }
        });
    }

    componentWillUnMount() {
        this
            .state
            .pan
            .x
            .removeAllListeners();
    }

    render() {
        //decouple the value from the state object
        let {pan} = this.state;
        let [translateX,
            translateY] = [pan.x, pan.y];
        let translateStyle = {
            transform: [{
                    translateX
                }, {
                    translateY
                }]
        };
        return (
            <View>
                <Text style={styles.leftText}>Power Button Demo</Text>
                <View style={styles.buttonStyle}>
                    <Animated.View
                        style={[styles.sliderButtonStyle, translateStyle]}
                        {...this._panResponder.panHandlers}>
                        <FontAwesome
                            name="power-off"
                            color="#EA2E49"
                            style={{
                            alignSelf: "center",
                            marginHorizontal: 10
                        }}
                            size={36}/>

                    </Animated.View>
                </View>
                <Text style={styles.rightText}>{this.state.panValue}: x value</Text>
            </View>
        );
    }
}

export default ClockInSwitch;
const styles = StyleSheet.create({
    sliderButtonStyle: {
        borderColor: '#FCFFF5',
        borderStyle: 'solid',
        borderWidth: .5,
        backgroundColor: '#FCFFF5',
        borderRadius: 45,
        height: 90,
        width: 90,
        justifyContent: 'center',
        textAlign: 'center',
        marginHorizontal: 5,
        shadowColor: '#333745',
        shadowOffset: {
            width: 2,
            height: 2
        },
        shadowOpacity: .6,
        shadowRadius: 5
    },
    buttonStyle: {
        borderColor: '#FCFFF500',
        backgroundColor: '#DAEDE255',
        borderStyle: 'solid',
        borderWidth: 1,
        height: 100,
        width: 300,
        justifyContent: 'center',
        borderRadius: 50,
        margin: 5,
        flexDirection: 'column'
    },
    rightText: {
        justifyContent: 'center',
        textAlign: 'right',
        fontWeight: '100',
        marginHorizontal:15,
        fontSize: 20,
        color: '#FCFFF5',
        marginVertical:25,
        flexDirection: 'column'
    },
    leftText: {
        justifyContent: 'center',
        textAlign: 'left',
        fontWeight: '100',
        marginHorizontal:15,
        fontSize: 24,
        color: '#FCFFF5',
        marginVertical:25,
        flexDirection: 'column'
    }
});
&#13;
&#13;
&#13;