美文网首页
RotationGestureHandler - react-n

RotationGestureHandler - react-n

作者: JamesSawyer | 来源:发表于2019-04-03 23:03 被阅读0次

文档来源:

连续类型handler, 用于识别旋转手势.

识别方式:

  • 手指放置在屏幕上,然后以合适的方式改变手指的位置

这个手势iOS中使用 UIRotationGestureRecognizer 实现,Android中则自定义实现

属性(Properties)

注意这个handler没有扩展通用的handler属性,下面是 RotationGestureHandler的属性:

  • rotation:手势旋转的度数,单位 弧度(radians
  • velocity:当前动作滑动手势的速度,单位 points/second
  • focalX:中心锚点沿着X轴的位置,单位是 points
  • focalY:同上,针对Y轴

示例

import React, { PureComponent } from 'react';
import { StyleSheet, Animated } from 'react-native';
import { PanGestureHandler, PinchGestureHandler, RotationGestureHandler, State } from 'react-native-gesture-handler';

import { USE_NATIVE_DRIVER } from '../config';

const styles = StyleSheet.create({

  container: {
    ...StyleSheet.absoluteFillObject,
    overflow: 'hidden',
    alignItems: 'center',
    justifyContent: 'center',
    flex: 1,
    backgroundColor: '#6ac',
  },
  pinchableImage: {
    width: 250,
    height: 250,
  },
  wrapper: {
    flex: 1,
  },
})

export default class PinchableBox extends PureComponent {
  panRef = React.createRef();
  rotationRef = React.createRef();
  pinchRef = React.createRef();

  constructor(props) {
    super(props);

    /**
     * 缩放
     */
    this._baseScale = new Animated.Value(1); // 基础缩放
    this._pinchScale = new Animated.Value(1); // 手指缩放的值
    this._scale = Animated.multiply(this._baseScale, this._pinchScale); // 缩放值 = 基础缩放 * 手指缩放的值
    this._lastScale = 1; // 将pinch 完成之后的缩放值
    this._onPinchGestureEvent = Animated.event(
      [
        {
          nativeEvent: {
            scale: this._pinchScale,
          },
        },
      ],
      { useNativeDriver: USE_NATIVE_DRIVER },
    );

    /**
     * 旋转
     */
    this._rotate = new Animated.Value(0);
    // 插值
    this._rotateStr = this._rotate.interpolate({
      inputRange: [-100, 100],
      outputRange: ['-100rad', '100rad'], // 单位为 rad
    });
    this._lastRotate = 0;
    this._onRotateGestureEvent = Animated.event(
      [
        { nativeEvent: { rotation: this._rotate } }
      ],
      { useNativeDriver: USE_NATIVE_DRIVER },
    );

    /**
     * Tilt 倾斜
     */
    this._tilt = new Animated.Value(0);
    this._tiltStr = this._tilt.interpolate({
      inputRange: [-501, -500, 0, 1], // 注意这里的 -501 500, 表示临界情况
      outputRange: ['1rad', '1rad', '0rad', '0rad'],
    });
    this._lastTilt = 0;
    this._onTiltGestureEvent = Animated.event(
      [
        {nativeEvent: { translationY: this._tilt }},
      ],
      { useNativeDriver: USE_NATIVE_DRIVER },
    );
  }

  // 旋转
  _onRotateHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      this._lastRotate += event.nativeEvent.rotation;
      this._rotate.setOffset(this._lastRotate);
      this._rotate.setValue(0)
    }
  }

  // 缩放
  _onPinchHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      this._lastScale *= event.nativeEvent.scale;
      this._baseScale.setValue(this._lastScale); // 将 基础缩放 设置为最后产生的缩放
      this._pinchScale.setValue(1); // 将手指产生的缩放设置为初始值1
    }
  }

  // 沿着X轴旋转
  _onTiltGestureStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      this._lastTilt += event.nativeEvent.translationY;
      this._tilt.setOffset(this._lastTilt);
      this._tilt.setValue(0);
    }
  }

  render() {
    return (
      <PanGestureHandler
        ref={this.panRef}
        onGestureEvent={this._onTiltGestureEvent}
        onHandlerStateChange={this._onTiltGestureStateChange}
        minDist={10}
        minPointers={2}
        maxPointers={2}
        avgTouches
      >
        <Animated.View style={styles.wrapper}>
          <RotationGestureHandler
            ref={this.rotationRef}
            simultaneousHandlers={this.pinchRef}
            onGestureEvent={this._onRotateGestureEvent}
            onHandlerStateChange={this._onRotateHandlerStateChange}
          >
            <Animated.View style={styles.wrapper}>
              <PinchGestureHandler
                ref={this.pinchRef}
                simultaneousHandlers={this.rotationRef}
                onGestureEvent={this._onPinchGestureEvent}
                onHandlerStateChange={this._onPinchHandlerStateChange}
              >
                <Animated.View style={styles.container} collapsable={false}>
                  <Animated.Image
                    style={[
                      styles.pinchableImage,
                      {
                        transform: [
                          { perspective: 200 },
                          { scale: this._scale },
                          { rotate: this._rotateStr },
                          { rotateX: this._tiltStr },
                        ]
                      }
                    ]}
                    source={require('./juice.jpeg')}
                  />
                </Animated.View>
              </PinchGestureHandler>
            </Animated.View>
          </RotationGestureHandler>
        </Animated.View>
      </PanGestureHandler>
    )
  }
}

这是一个综合示例,涉及到多个知识点:

  • 跨handlers之间的交互
  • simultaneousHandlers 属性的使用: 接受一个react ref对象或者 refs数组。使用这个属性,则会允许同时存在多个handlers被激活的情况。当handlers激活时,它会阻止提供的handlers取消当前的handler
  • Animated 属性的使用
    • Animated.multiply
    • 插值函数:this._rotate.interpolate()
    • <Animated.View> | <Animated.Image> , <Animated.View> 在多个Handlers之间充当中间层的作用
    • setOffset()
    • setValue()

相关文章

网友评论

      本文标题:RotationGestureHandler - react-n

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