javascript - 在第二个输入上 react native 动画 PanResponder 反转

标签 javascript reactjs animation react-native draggable

我得到了一个使用 PanResponder 与 React Native API 的动画相结合的组件。我的组件的代码:

import React, { Component } from 'react';
import { Animated, PanResponder } from 'react-native';

import { SVG } from '../';
import { Icon, LockContainer, StatusCircle } from './styled';

class VehicleLock extends Component {
  state = {
    pan: new Animated.ValueXY({ x: 9, y: 16 }),
  };

  componentWillMount() {
    this.animatedValueY = 0;

    this.minYValue = 16;
    this.maxYValue = 175;

    this.state.pan.y.addListener((value) => {
      this.animatedValueY = value.value;
    });

    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponderCapture: () => true,
      onMoveShouldSetPanResponderCapture: () => true,

      onPanResponderGrant: (evt, gestureState) => {
        this.state.pan.setOffset({ x: 0, y: 0 });
        // this.state.pan.setOffset(this.state.pan.__getValue());
        this.state.pan.setValue({ x: 9, y: this.minYValue });
      },
      onPanResponderMove: (evt, gestureState) => {
        // deltaY: amount of pixels moved vertically since the beginning of the gesture
        let newY = gestureState.dy;

        if (newY < this.minYValue) {
          newY = this.minYValue;
        } else if (newY > this.maxYValue) {
          newY = this.maxYValue;
        }

        Animated.event([null, {
          dy: this.state.pan.y,
        }])(evt, {
          dy: newY,
        });
      },
      onPanResponderRelease: (evt, gestureState) => {
        let newY = this.minYValue;
        const releaseY = gestureState.dy;

        if (releaseY > 83) {
          newY = this.maxYValue;
        }

        Animated.spring(this.state.pan, {
          toValue: {
            x: 9,
            y: newY,
          },
        }).start();
      },
    });
  }

  componentWillUnmount() {
    this.state.pan.x.removeAllListeners();
    this.state.pan.y.removeAllListeners();
  }

  render() {
    const customStyles = {
      ...this.state.pan.getLayout(),
      position: 'absolute',
      zIndex: 10,
      transform: [
        {
          rotate: this.state.pan.y.interpolate({
            inputRange: [this.minYValue, this.maxYValue],
            outputRange: ['0deg', '180deg'],
          }),
        },
      ],
    };

    return (
      <LockContainer>
        <SVG icon="lock_open" width={16} height={21} />

        <Animated.View
          {...this.panResponder.panHandlers}
          style={customStyles}
        >
          <StatusCircle>
            <Icon>
              <SVG icon="arrow_down" width={23} height={23} />
            </Icon>
          </StatusCircle>
        </Animated.View>

        <SVG icon="lock_closed" width={16} height={21} />
      </LockContainer>
    );
  }
}

export default VehicleLock;

正如您在我的代码中看到的,我使用边界对 Y 值进行动画处理。它必须保持在某些值之间的框中。一旦用户释放拖动并且它超过最大 Y 值的一半,它就会动画到最大值。

这可以正常工作,但在第二次交互时我想反转该操作。因此,它必须上涨,而不是下跌。不幸的是,发布后 Y 值会重置。

正如您在我的代码中的注释中所看到的,我知道移动是基于增量的,因此自交互开始以来移动的 Y 值。这个伟大的评论对此进行了解释PanResponder snaps Animated.View back to original position on second drag

虽然我不知道如何解决它。在这里您可以看到我当前的行为: enter image description here

在第二个输入时,元素弹回到顶部。这是预期的行为。正如 @jevakallio 在他的评论中所述,您可以在 onPanResponderGrant 中重置偏移量中的值。当我这样做时(已注释掉),元素会重置值,但在第二次交互时,它将在容器外部进行动画处理。因此,在这种情况下,0maxYValue,它会将容器外部的 175 动画到底部。

如何制作一个反转的动画,从外面回到顶部?我似乎不太明白这一点。提前致谢!

最佳答案

根据Panresponder docs onPanResponderGrant 应指示手势的开始。因此,如果您此时设置 this.state.pan.setOffsetthis.state.pan.setValue,它将在每个手势开始时重置。尝试在 onPanResponderGrant 中查看 console.log,看看会发生什么。

此外,实现 PanResponder 的父组件或包装组件可能会干扰您的 PanResponder。这可能是解决问题的另一个良好起点。

来自 PanResponder 文档:

onPanResponderGrant: (evt, gestureState) => {
    // The gesture has started. Show visual feedback so the user knows
    // what is happening!

    // gestureState.d{x,y} will be set to zero now
  },

关于javascript - 在第二个输入上 react native 动画 PanResponder 反转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50511918/

相关文章:

javascript - SVG JavaScript/ECMAScript API

javascript - 从 db Firebase 获取用户

javascript - require 关键字周围的 try catch block

javascript - 我们可以通过多少种方式将 Prop 传递给 react 中的所有子组件

javascript - 多个状态在 React 中共享相同的 View 或组件

ios - 创建一个带条件的动画加载框架,而不是动画启动屏幕

javascript - 如何用纯Javascript制作锁屏并输入密码解锁?

javascript - React/Node 文件在 Safari 中上传失败

animation - 如何用 Flutter 在同屏路线上制作英雄风格的动画?

xaml - WPF 淡入淡出动画