我们已经使用 React Native PanResponder 开发了一个 swiper(在有人评论之前) - 我们不能在这里使用任何其他 swiper 库。在我们开发的滑动器中,当用户结束滑动(意味着释放平移)时,我们面临一个问题,启动弹簧动画时会出现滞后。
因此,为了解决这个问题,我们正在尝试从React Native Animated API迁移到Reanimated Libary,这可以解决用户面临的延迟问题。
但是,在使用React Native Gesture Handler (PanGestureHandler) 和 Reanimated Library 进行开发时,我们无法检测手势处理程序中的滑动方向。
我添加了用于检测 PanResponder 中滑动方向的代码部分
onPanMoving = (evt, {dx}) => {
this.draggedEnd = dx < -this.swipeThreshold; //You are moving towards right screen
this.draggedStart = dx > this.swipeThreshold; //You are moving towards left screen
}
Run Code Online (Sandbox Code Playgroud)
如您所见,在 PanResponder 中检测平移移动时的方向非常容易。
手势处理程序的问题来了,
当手势状态处于活动状态时,我无法检测到滑动
我已经在手势处理程序中搜索了问题,并发现了这个。
该问题中建议了两种解决方法
react-native react-native-reanimated react-native-gesture-handler
我正在使用带有和 的react-native-gesture-handler库。我想让scrollView可滚动,它嵌套在panGestureHandler中,但所有交互都是由 处理的,所以scrollView不起作用。这是我的代码。reanimatedreact-native-redashpanGestureHandler
VideoModal.js文件
import Animated , {useCode , cond , eq , set , add, block, interpolate, Extrapolate} from "react-native-reanimated"
import {PanGestureHandler , State } from "react-native-gesture-handler"
import {usePanGestureHandler , useValue , timing , snapPoint} from "react-native-redash/lib/module/v1"
export default function VideoModal(props) {
const { video } = props;
const {gestureHandler , velocity , translation , state} = usePanGestureHandler()
const translateY = useValue(0)
const offsetY = useValue(0);
const snapPoints = snapPoint(translateY , velocity.y , …Run Code Online (Sandbox Code Playgroud) 这是我的组件。很简单,PanGestureHandler有一些 svg。
import React from 'react'
import { StyleSheet, View, Text } from 'react-native'
import Svg, { Circle, Line } from 'react-native-svg'
import Layout from '../constants/Layout'
import {
PanGestureHandler,
TapGestureHandler
} from 'react-native-gesture-handler'
import Animated, {
useSharedValue,
useAnimatedGestureHandler,
useAnimatedProps,
withTiming,
Easing
} from 'react-native-reanimated'
const AnimatedCircle = Animated.createAnimatedComponent(Circle)
const chartWidth = Layout.window.width
const chartHeight = chartWidth / 2.6
const timing = 200
export default function Chart () {
const x = useSharedValue(chartWidth / 2)
const y = useSharedValue(chartHeight …Run Code Online (Sandbox Code Playgroud) react-native react-native-reanimated react-native-gesture-handler react-native-reanimated-v2
我正在尝试从平移手势(React Native Gesture Handler)更改状态。
const [localShowRecents, setLocalShowRecents] = useState(false)
const translateY = useSharedValue(0);
const gesture = Gesture.Pan()
.onStart(() => {
context.value = { y: translateY.value }
})
.onUpdate((event) => {
//console.log(event.translationY);
translateY.value = event.translationY + context.value.y;
translateY.value = Math.max(translateY.value, MAX_TRANSLATE_Y)
})
.onEnd(() => {
if (translateY.value > -SCREEN_HEIGHT / 32){
setLocalShowRecents(true); //change state
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试从“.onEnd()”函数更新状态时,收到错误“尝试从不同线程同步调用函数”。如何正确更改手势处理程序的状态?
javascript asynchronous reactjs react-native react-native-gesture-handler
有一些手势处理程序可以在浏览器中正常工作,但我在 iOS 上的 useAnimatedGestureHandler 挂钩的 onEnd 回调中收到此错误。
这是与我尝试添加的手势相关的所有代码
const headerHeight = useSharedValue(176)
const outerStyle = useAnimatedStyle(() => ({
minHeight: 176,
maxHeight: 416,
height: headerHeight.value,
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20,
position: 'relative',
overflow: 'visible',
zIndex: 502,
}))
const innerStyle = useAnimatedStyle(() => ({
overflow: 'hidden',
height: headerHeight.value,
minHeight: 176,
maxHeight: 416,
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20,
}))
const resizeHeaderHeight = useAnimatedGestureHandler({
onStart: () => {},
onActive: (event) => {
headerHeight.value = event.absoluteY
},
onEnd: () => {
if(headerHeight.value < 305) {
headerHeight.value = …Run Code Online (Sandbox Code Playgroud) react-native react-native-reanimated react-native-gesture-handler react-native-reanimated-v2
我正在关注本教程:https://youtu.be/r5XXSb4yQes(代码: https: //github.com/wcandillon/can-it-be-done-in-react-native/tree/master/season3/src/ CoinbasePro)并按照他所说的做了,但我无法使洗涤器(水平和垂直线)工作。
如您所见,即使我按下/拖动,滑块/线也不会出现。
PanGestureHandler 触发时预期的水平线和垂直线:
下面是相关代码:
主屏幕:
import Animated, {
add,
diffClamp,
eq,
modulo,
sub,
} from "react-native-reanimated";
import { useValues, onGestureEvent } from "react-native-redash/lib/module/v1";
import { PanGestureHandler, State } from "react-native-gesture-handler";
import Svg, { Line } from "react-native-svg";
import data from "../../utils/data";
const MainScreen = () => {
const caliber = data.length > 0 ? width / data.length : 0;
const [x, y, state] = useValues(0, 0, State.UNDETERMINED);
const gestureHandler = onGestureEvent({ x, …Run Code Online (Sandbox Code Playgroud) javascript react-native react-native-reanimated react-native-gesture-handler react-native-reanimated-v2
我使用react-native-gesture-handler和react-native-reanimated构建了捏合缩放效果。用户可以在图像的任意位置捏合,以手指之间的位置为缩放原点进行放大或缩小。这很棒。我遇到的问题是允许用户以多个捏合手势放大或缩小。这需要记住用户之前的捏合手势的偏移量和缩放比例。使用我当前拥有的代码,当用户第二次捏合时,手势处理程序会记住第一次捏合手势的缩放比例值,不会正确更新缩放原点。如何在不增加转换语句数量的情况下解决此问题?
const prevZoomScale = useSharedValue(1)
const currZoomScale = useSharedValue(1)
const zoomScale = useDerivedValue(() => { return prevZoomScale.value * currZoomScale.value }, [prevZoomScale.value, currZoomScale.value])
const tempZoomScale = useSharedValue(1)
const prevOriginOffset = useSharedValue({x: 0, y: 0})
const tempOriginOffset = useSharedValue({x: 0, y: 0})
const currOriginOffset = useSharedValue({x: 0, y: 0})
const pinchOriginOffset = useDerivedValue(() =>
{
return {
x: (prevOriginOffset.value.x + currOriginOffset.value.x),
y: (prevOriginOffset.value.y + currOriginOffset.value.y)
}
},
[prevOriginOffset.value.x, prevOriginOffset.value.y, currOriginOffset.value.x, currOriginOffset.value.y]
)
const onPinchEvent = useAnimatedGestureHandler<PinchGestureHandlerGestureEvent>({
onStart: (_) => {
prevZoomScale.value = …Run Code Online (Sandbox Code Playgroud) animation gesture react-native react-native-reanimated react-native-gesture-handler
我尝试GestureDetector使用react-native-gesture-handler
import React from 'react';
import { Directions, Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
/**
* Component used as Home Page
*/
const HomePage: React.FC = () => {
const position = useSharedValue(0);
const trigger = () => {
console.log('fdfs')
}
const flingGesture = Gesture.Fling()
.direction(Directions.RIGHT)
.onStart((e) => {
position.value = withTiming(position.value + 10, { duration: 100 });
console.log(e)
// trigger()
});
const flingGestureLeft = Gesture.Fling()
.direction(Directions.LEFT)
.onStart((e) => …Run Code Online (Sandbox Code Playgroud) 在下面的简单滑块(打字稿)示例中,react-native-gesture-handler 中的 PanGestureHandler 仅在手势启动后才会设置。用户需要移动手指。
这就是我想要实现的目标:点击还应该设置滑块值(包括点击和拖动)。这是一种常见模式,例如在搜索视频文件或将音量设置为最大然后进行调整时。
我想我可以将其包装在 TapGestureHandler 中,但我正在寻找最优雅的方法来实现这一目标,而无需太多样板。
// example extracted from https://www.npmjs.com/package/react-native-reanimated-slider
import React, { Component } from 'react';
import Animated from 'react-native-reanimated';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
const { Value, event, cond, eq, Extrapolate, interpolate } = Animated;
interface IProps {
minimumTrackTintColor: string;
maximumTrackTintColor: string;
cacheTrackTintColor: string;
value: number;
style: any;
cache;
onSlidingStart;
onSlidingComplete;
}
class Slider extends Component<IProps, {}> {
static defaultProps = {
minimumTrackTintColor: '#f3f',
maximumTrackTintColor: 'transparent',
cacheTrackTintColor: '#777',
};
private gestureState;
private x; …Run Code Online (Sandbox Code Playgroud) react-native react-native-reanimated react-native-gesture-handler
我无法使用酶、笑话和反应本机测试库来测试反应本机应用程序。
\n\n仅进行渲染测试
\n\nit('renders correctly', () => {\n renderer.create(<App />).toJSON;\n});\nRun Code Online (Sandbox Code Playgroud)\n\n我收到这个错误
\n\n失败 测试/App-test.js\n \xe2\x97\x8f 测试套件运行失败
\n\nTypeError: Cannot read property 'Direction' of undefined\n\n at Object.<anonymous> (node_modules/react-native-gesture-handler/Directions.js:3:33)\n at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:2:42)\nRun Code Online (Sandbox Code Playgroud)\n\n测试套件:1 次失败,总共 1 次\n测试:总共 0 次\n快照:总共 0 次\n时间:1.586 秒\n运行所有测试套件。\nnpm 错误!测试失败。请参阅上文了解更多详情。
\n错误

我正在学习 React Native 手势处理程序和 React Native Reanimated 从文档中。当我获取手势坐标并将其传递给 useShared 值 translateX 时,出现此错误。我在运行 android 8.0.0 的 Samsung Galaxy A5 2017 上运行我的应用程序。请解释你的答案。
应用程序.js
// import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import { StyleSheet, Text, View,StatusBar,TouchableOpacity } from 'react-native';
import Animated, {useSharedValue, useAnimatedStyle, withTiming,withSpring,withRepeat} from 'react-native-reanimated'
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { NavigationContainer } from '@react-navigation/native';
import Header from './components/Header';
import Gesture from './screens/Gesture';
const SimpleAnimation=({navigation})=>{
const SIZE=100.0
const handleRotation=(progress)=>{
"worklet";
return `${progress.value*2*Math.PI}rad`;
} …Run Code Online (Sandbox Code Playgroud) react-native react-native-reanimated react-native-gesture-handler react-native-reanimated-v2
这是在我意识到 onStart() 没有被调用之前
使用 PanGestureHandler 并尝试“拖动”AnimatedView 在网络上不起作用。没有明显的错误,应用程序构建得很好,检查时控制台中没有警告。
有一个警告让我相信这可能是问题的根源。我在控制台中收到一条警告,内容如下:
"transform" style array value is deprecated. Use space-separated string functions, e.g., "scaleX(2) rotateX(15deg)".
我使用带有 containerStyle 样式的 AnimatedView 来转换对象并在拖动时移动它。
问题的根源
所以我一直在进一步研究它,尝试调试它,我开始意识到回调onStart()没有被调用。由于onStart()未调用回调,因此上下文值永远不会最终被设置,并且上下文对象总体保持为空。导致我最初的问题是无法拖动对象。
不过,这在 iOS 上仍然有效。由于某种原因,在 iOS 上onStart()会调用回调。这会导致上下文被填充并起作用。
这是到目前为止我的代码,请记住这只是一个组件。在根目录中,我确实有一个包含整个应用程序的 GestureHandlerRootView 组件。
import { View, Image } from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
useAnimatedGestureHandler,
withSpring,
} from 'react-native-reanimated';
import { PanGestureHandler, TapGestureHandler } from 'react-native-gesture-handler';
const AnimatedImage = Animated.createAnimatedComponent(Image);
const AnimatedView = Animated.createAnimatedComponent(View);
export default function EmojiSticker ({ imageSize, …Run Code Online (Sandbox Code Playgroud) reactjs react-native react-animated react-native-web react-native-gesture-handler
我有一个堆栈导航,我想在 android 和 IOS 上启用滑动返回,这是我的代码
import {
createStackNavigator,
StackViewTransitionConfigs,
} from "react-navigation-stack";
import HomeScreen from "../../screens/Home/Home";
import CategoryScreen from "../../screens/Category/Category";
import SubCategoryScreen from "../../screens/SubCategory/SubCategory";
import ProductScreen from "../../screens/Product/Product";
const ShopStack = createStackNavigator(
{
Shop: {
screen: HomeScreen,
navigationOptions: {
gesturesEnabled: true,
},
},
Category: {
screen: CategoryScreen,
navigationOptions: {
gesturesEnabled: true,
},
},
SubCategory: {
screen: SubCategoryScreen,
},
Product: {
screen: ProductScreen,
navigationOptions: {
gesturesEnabled: true,
},
},
},
{
headerMode: "none",
transitionConfig: () => StackViewTransitionConfigs.SlideFromRightIOS,
defaultNavigationOptions: {
gesturesEnabled: true, …Run Code Online (Sandbox Code Playgroud) react-native react-navigation react-navigation-stack react-native-gesture-handler
react-native-gesture-handler ×13
react-native ×11
reactjs ×3
javascript ×2
animation ×1
asynchronous ×1
enzyme ×1
fling ×1
gesture ×1
jestjs ×1
native ×1