美文网首页
react-native 组件Transforms属性+Ani

react-native 组件Transforms属性+Ani

作者: CaoJelly | 来源:发表于2019-04-02 16:19 被阅读0次

react-native transforms 实现动画:

通过组件style 内提供的 transforms 属性来实现改变组件坐标角度旋转等(xyz三坐标轴)
transforms 接收的是array 类型
array of object: {perspective: number}, ,object: {rotate: string}, ,object: {rotateX: string}, ,object: {rotateY: string}, ,object: {rotateZ: string}, ,object: {scale: number}, ,object: {scaleX: number}, ,object: {scaleY: number}, ,object: {translateX: number}, ,object: {translateY: number}, ,object: {skewX: string}, ,object: {skewY: string}

perspective:透视程度; rotate: 旋转角度 ,rotateX x 轴旋转 , rotateY y轴旋转 ,rotateZ z轴旋转 ;scale:缩放; translate 位移; skew:倾斜度

本案例通过 组件onLayout属性 获取组件在当前父视图中的坐标,在通过手势位移去改变组件的坐标.

git地址:https://github.com/CJELLYS/react-native-transform-demo

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, {Component} from 'react';
import {
  Platform, 
  StyleSheet, 
  Text, 
  View,
  TouchableOpacity,
  PanResponder,
  Animated,
  Dimensions
} from 'react-native';
import {NativeModules} from 'react-native';
const AppDelegate = NativeModules.AppDelegate;

type Props = {};

const widthScreen = Dimensions.get('window').width;
const rotateXDeg = 90.0 //x轴最终旋转的角度为90度
const offsetX = (widthScreen -80)/2.0 //为 终点坐标左上角X轴坐标位置
const offsetY = 50 //200 为终点左上角Y轴坐标位置
const offsetUnitX = (offsetX - 50)/rotateXDeg//x轴单位位移量 180 为 获取到的组件坐标的x值+组件宽度 50 为 组件初始x轴坐标值
const offsetUnitY = (offsetY-100)/rotateXDeg //y轴单位位移量   100 为 获取到的组件坐标的y值+组件宽度 ;

export default class App extends Component<Props> {
 
  constructor(props){
    super(props)
    this.state =({
      textRotateX:0,//X轴旋转
      translateX:new Animated.Value(0),//X轴位移
      translateY:new Animated.Value(0),//Y轴位移
    });
    this.textRotateX = 0
    this.translateX = 0
    this.translateY = 0
  }

  checkAction(){
    console.log("NativeModules=>",AppDelegate);
    if(AppDelegate){
      AppDelegate.addEvent('Birthday Party', '4 Privet Drive, Surrey');
    }
  }

  componentWillMount(){
    if(!this._panResponder)
    this._panResponder = PanResponder.create({
      // 要求成为响应者:
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      // onMoveShouldSetPanResponder: (evt, gestureState) => true,
      // onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

      onPanResponderGrant: (evt, gestureState) => {
        // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!

        // gestureState.{x,y} 现在会被设置为0
        // console.log("===>>0",'开始手势操作');
      },
      onPanResponderMove: (evt, gestureState) => {
        // 最近一次的移动距离为gestureState.move{X,Y}

        // 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
        if(this.textRotateX < -rotateXDeg){
          this.textRotateX = -rotateXDeg;
          this.setState({
            textRotateX:this.textRotateX
          })
          return
        }
        if(gestureState.dy < 0 && this.textRotateX> -rotateXDeg){
          this.textRotateX = this.textRotateX -1;
          this.translateX = this.translateX + offsetUnitX;
          this.translateY = this.translateY + offsetUnitY ;
          this.setState({
            textRotateX:this.textRotateX
          })
          Animated.parallel([
            // 执行缩放
            Animated.timing(this.state.translateX, {
                toValue: this.translateX,
                duration: 0,
            }),
            Animated.timing(this.state.translateY, {
                toValue: this.translateY,
                duration: 0,
            })
        ]).start();

        }else if(gestureState.dy > 0 && this.textRotateX <= 0){
          this.textRotateX = this.textRotateX +1;
          this.translateX = this.translateX - offsetUnitX;
          this.translateY = this.translateY - offsetUnitY ;
          this.setState({
            textRotateX:this.textRotateX
          })
           Animated.parallel([
            // 执行缩放
            Animated.timing(this.state.translateX, {
                toValue: this.translateX,
                duration: 0,
            }),
            Animated.timing(this.state.translateY, {
                toValue: this.translateY,
                duration: 0,
            })
        ]).start();
        }
      },

      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onPanResponderRelease: (evt, gestureState) => {
        // 用户放开了所有的触摸点,且此时视图已经成为了响应者。
        // 一般来说这意味着一个手势操作已经成功完成。
        // console.log("用户放开",gestureState.moveX,gestureState.moveY);

        if(this.textRotateX > -rotateXDeg/2.0 && this.textRotateX < rotateXDeg/2.0){
          this.textRotateX = 0  
          this.translateX = 0;
          this.translateY = 0;
          this.setState({
            textRotateX:this.textRotateX
          })
          Animated.parallel([
          Animated.spring(this.state.translateX,
            { 
              toValue: this.translateX,
              duration: 500
            }),
          Animated.spring(this.state.translateY,
          { 
            toValue: this.translateY,
            duration: 500
          })
        ]).start()
        }else{
          this.textRotateX = -rotateXDeg
          this.translateX = offsetX - 50;
          this.translateY = (offsetY-100);
          this.setState({
            textRotateX:this.textRotateX
          })
          Animated.parallel([
            Animated.spring(this.state.translateX,
              { 
                toValue: this.translateX,
                duration: 500
              }),
            Animated.spring(this.state.translateY,
            { 
              toValue: this.translateY,
              duration: 500
            })
          ]).start()
        }
        
      },
      onPanResponderTerminate: (evt, gestureState) => {
        // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
        console.log("===>>3",'另一个组件');
      },
      onShouldBlockNativeResponder: (evt, gestureState) => {
        // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
        // 默认返回true。目前暂时只支持android。
        return true;
      },
    });
  }

  getAnimatedView(event){
    let {x,y,width,height} = event.nativeEvent.layout
    console.log("xxxxxxx==>",x,y,width,height)
  }

  render() {
    return (
      <View style={styles.container} {...this._panResponder.panHandlers}>
      <Animated.View style={{
        width:80,
        height:80,
        marginTop:100,
        marginLeft:50,
        backgroundColor:'red',
        borderRadius:40,
        transform:[{translateX:this.state.translateX},{translateY:this.state.translateY}]
      }}
      onLayout = {this.getAnimatedView.bind(this)}
      ref={(animatedView)=>this.animatedView = animatedView}
      >
      </Animated.View>
       <Text style={{
         fontSize:12,
         height:30,
         width:80,
         marginLeft:200,
         marginTop:30,
         backgroundColor:'cyan',
         alignItems:'center',
         justifyContent:'center',
         transform:[{ rotateX: this.state.textRotateX +'deg'}],
         marginBottom:30
       }}>{'Hello'}</Text>       
        <TouchableOpacity 
        onPress={this.checkAction.bind(this)}
        style={{width:80,height:40,alignItems:'center',justifyContent:'center',backgroundColor:'cyan'}}>
          <Text>验证</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
});


相关文章

网友评论

      本文标题:react-native 组件Transforms属性+Ani

      本文链接:https://www.haomeiwen.com/subject/xumgbqtx.html