0

用例

我需要利用PanResponder用手指移动视图。一旦手指从屏幕上抬起,视图应该以动量保持在移动方向上移动,并以减速的速度停止

问题

我可以使用Animated.decay方法实现用例onPanResponderRelease。但是当我再次开始移动视图时,它会捕捉到与其位置的偏移量。

pan.flattenOffset()按照 PanResponder 文档中的示例进行了尝试,但这没有帮助。只要我不使用Animated.decay方法,它就可以工作。

onPanResponderRelease: (_, { vx, vy }) => {
  // pan.flattenOffset() alone works but then there's no momentum on release

  Animated.parallel([
    Animated.decay(pan.x, {
      velocity: vx,
      useNativeDriver: true,
    }),
    Animated.decay(pan.y, {
      velocity: vy,
      useNativeDriver: true,
    }),
  ]).start(() => pan.flattenOffset()); // pan.flattenOffset doesn’t work here
},

显示有和没有动量运动的 GIF

有动力的 PanResponder PanResponder 没有动力
有动力的 PanResponder PanResponder 没有动力

代码

import React, { useRef } from 'react';

import {
  View,
  Animated,
  StyleSheet,
  PanResponder,
  SafeAreaView,
} from 'react-native';

const App = () => {
  const pan = useRef(new Animated.ValueXY()).current;

  const panResponder = useRef(
    PanResponder.create({
      onMoveShouldSetPanResponder: () => true,
      onPanResponderGrant: () => pan.setOffset({ x: pan.x._value, y: pan.y._value }),
      onPanResponderMove: Animated.event(
        [null, { dx: pan.x, dy: pan.y }],
        { useNativeDriver: false },
      ),
      // this alone works
      // onPanResponderRelease: () => {
      //   pan.flattenOffset();
      // },
      onPanResponderRelease: (_, { vx, vy }) => {
        Animated.parallel([
          Animated.decay(pan.x, {
            velocity: vx,
            useNativeDriver: true,
          }),
          Animated.decay(pan.y, {
            velocity: vy,
            useNativeDriver: true,
          }),
        ]).start(() => pan.flattenOffset()); // pan.flattenOffset doesn’t work here
      },
    }),
  ).current;

  return (
    <SafeAreaView style={styles.container}>
      <Animated.View
        style={[{ transform: [{ translateX: pan.x }, { translateY: pan.y }] }]}
        {...panResponder.panHandlers}
      >
        <View style={[styles.point]} />
      </Animated.View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  point: {
    width: 30,
    height: 30,
    borderRadius: 15,
    backgroundColor: '#000',
  },
});

export default App;
4

0 回答 0