reactjs - 为什么 React Native Panresponder 中存在 'offset'?

标签 reactjs react-native animation gesture

TL;博士 :我正在使用 React Native 文档中的 Panresponder 代码,需要帮助理解为什么使用“偏移”值,而不是仅使用动画值。

完整问题 :

场景 :

我在 React Native 中使用 Panresponder 在屏幕上拖放对象。我正在使用 RN 文档中的标准代码。

基本上,可拖动对象具有动画位置值。当您单击对象时,该动画值的偏移量设置为动画值,动画值设置为零。当您拖动时,动画值会逐渐设置为在该手势中拖动的距离的大小。当您释放对象时,偏移量会添加到动画值中,然后偏移量设置为零。

示例:

例如,如果对象从位置 0 开始,那么最初动画值和偏移量都设置为 0。如果将对象拖动 100 像素,则动画值会随着拖动而逐渐从 0 增加到 100。当您释放时,零偏移量会添加到动画值中(因此没有任何 react )。如果再次单击对象,则偏移设置为 100,动画值重新设置为 0。如果将对象再拖动 50px,动画值从 0 增加到 50。释放对象时,100偏移量被添加到动画值,变为 150,并且偏移量重新设置为零。

这样,动画值始终保持当前手势中拖动的距离,偏移量保存对象在当前拖动手势开始之前所处的位置,当您释放对象时,保存的偏移量值将添加到动画值,以便当对象静止时,动画值包含对象被所有手势组合拖动的总距离。

代码:

这是我用来执行此操作的代码:

this.animatedValue.addListener((value) => this._value = value); // Make this._value hold the value of this.animatedValue (essentially extract the x and y values from the more complex animatedValue)
this.panResponder = PanResponder.create({
    onPanResponderGrant: () => { // When user clicks to initiate drag
        this.animatedValue.setOffset({ // Save 'distance dragged so far' in offset
            x: this._value.x,
            y: this._value.y,
        })
        this.animatedValue.setValue({ x: 0, y: 0}) // Set this.animatedValue to (0, 0) so that it will hold only 'distance so far in current gesture'
    },
    onPanResponderMove: Animated.event([ // As object is dragged, continually update animatedValue
        null, { dx: this.animatedValue.x, dy: this.animatedValue.y}
    ]),
    onPanResponderRelease: (e, gestureState) => { // On release, add offset to animatedValue and re-set offset to zero.
        this.animatedValue.flattenOffset();
    }
}

我的问题:

这段代码运行良好。当我不明白时,为什么我们需要偏移量?为什么我们需要在每个新手势上将动画值重新设置为零,将其值保存在偏移量中,并在拖动完成后将其重新添加到动画值中?当对象被释放时,它最终只是保持拖动的总距离,那么为什么不使用动画值而不使用偏移量呢?在我上面的例子中,为什么不在拖动它 100px 时将动画值增加到 100,然后当你再次单击并拖动它时,继续更新动画值?

可能的解决方案:

我能想到的使用偏移量的唯一优势是,animatedValue 现在将允许您跟踪“当前手势中的距离”,而不是“到目前为止所有手势组合的总距离”。在某些情况下,您可能需要“当前手势中的距离”值​​,所以我想知道这是否是使用偏移量的唯一原因,还是有更根本的原因我想念为什么我们应该一直用吗?

任何见解都会很棒。

谢谢!

最佳答案

实际上,您使用的示例中的逻辑不正确,因为它只是使用 的部分示例。 flattenOffset 这并不意味着用于标准拖/放行为(见底部段落: https://animationbook.codedaily.io/flatten-offset/ ):

Because we reset our offset and our animated value in the onPanResponderGrant, the call to flattenOffset is unnecessary, here. However, in the case where we want to trigger an animation from the released location to another location, flattenOffset is required.



偏移量的全部意义在于您不需要在单独的变量中跟踪绝对位置值。因此,鉴于您将绝对位置存储在 中,因此您怀疑是否需要偏移是正确的。 this._value .

在拖动开始时,Animated.Value 的 x/y 值从 [0, 0] 开始,因此拖动是相对于起始位置的:
  • 偏移量 + [0, 0] = 拖动开始处的绝对位置
  • offset + [x, y] = 拖动结束时的绝对位置

  • 要在正确的位置开始下一次拖动,您只需要将 [x, y] 添加到偏移量,这是由 完成的提取偏移() :
    this.panResponder = PanResponder.create({
        // Allow dragging
        onStartShouldSetPanResponder: (e, gesture) => true,
        // Update position on move
        onPanResponderMove: (e, gestureState)=> {
            Animated.event([
                null,
               {dx: this.animatedValue.x, dy: this.animatedValue.y},
            ])(e, gestureState)
        },
        // Update offset once we're done moving
        onPanResponderRelease: (e, gestureState)=> {
            this.animatedValue.extractOffset();
        }
    });
    

    由于偏移量,您不需要 this._value 再获得适当的拖动行为。

    关于reactjs - 为什么 React Native Panresponder 中存在 'offset'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55319640/

    相关文章:

    重新加载 JS 时,iOS React Native 应用程序在 JSCExecutor.cpp 中崩溃

    android - 在 Android 中的 Vertical Slider 中更改屏幕从右到左的方向过渡

    javascript - 如何在每次安装任何组件时刷新脚本?

    node.js - 如何在 React-Native 应用程序中包含并需要内置 Node 包?

    javascript - Redux reducer 被调用两次

    javascript - Wow JS 在页面加载时隐藏元素

    javascript - ng-animate 不适用于 animate.css

    reactjs - 错误 : Before running a Saga, 您必须使用 applyMiddleware 在 Store 上安装 Saga 中间件

    reactjs - 当我尝试在 useEffect 中 setState 时它不起作用

    javascript - 如何使用 reactjs redux 将新记录附加到已显示的记录