文档来源:
连续类型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()