反应原生动画不流畅

K.W*_*.Wu 5 animation reactjs react-native

我在 a 上面写了一个粘性标题FlatList,我有我想要的,看下面的图片,但是有两个问题。我想要的效果是:

  1. 首先图片的高度是170

  2. 当用户向上滚动时,图片也会向上滚动

  3. 但是当用户滚动 100 时,图片停止向上并停留在那里(意味着显示图片的底部 70)

  4. 同时,当用户滚动时,不透明度从 1 减少到最小值 0.5

代码在GIF下面

在此输入图像描述

const { width: SCREEN_WIDTH } = Dimensions.get('window');

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

const FULL_HEADER_HEIGHT = 170;
const DEFAULT_HEADER_HEIGHT = 70;
const HEADER_DIFF = FULL_HEADER_HEIGHT - DEFAULT_HEADER_HEIGHT;

class TestScreen extends Component {
    constructor(props) {
        super(props);

        this.state = {
            data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
        };

        this.scrollY = new Animated.Value(0);    // How many pixels scrolled

        this.headerOpacity = this.scrollY.interpolate({
            inputRange: [0, HEADER_DIFF, HEADER_DIFF + 1],
            outputRange: [1, 0.5, 0.5]
        });

        this.headerPositionY = this.scrollY.interpolate({
            inputRange: [0, HEADER_DIFF, HEADER_DIFF + 1],
            outputRange: [0, -HEADER_DIFF, -HEADER_DIFF]
        });
    }

    render() {
        return (
            <View style={{ ... }}>
                <Animated.View
                    style={{
                        transform: [{ translateY: this.headerPositionY }],
                        opacity: this.headerOpacity
                    }}
                >
                    <Image
                        source={...}
                        style={{ width: '100%', height: FULL_HEADER_HEIGHT }}
                        resizeMode='cover'
                    />
                </Animated.View>
                <AnimatedFlatList
                    data={this.state.data}
                    keyExtractor={(item) => item}
                    renderItem={({ item }) => (...)}
                    onScroll={Animated.event([{ nativeEvent: contentOffset: { y: this.scrollY } }], { useNativeDriver: true })}
                />
            </View>
        );
    }
}

export default TestScreen;
Run Code Online (Sandbox Code Playgroud)

问题1

动画不流畅

问题2

当图像上升时,它的容器似乎保持静止,当元素FlatList消失时,它们不会消失在图片的底部,它们消失在原始图片的底部,高度为170

cgl*_*cet 1

react-native: 0.55.4我想我在 iPhone 6(真实设备)上也有类似的问题。我尝试向动画值添加一个侦听器,如下所示:

18:24:57.157 Object {value: -39.919418166496385}
18:24:57.175 Object {value: -39.76205524921881}
18:24:57.200 Object {value: -39.42250543249108}
18:24:57.235 Object {value: -38.74063147167402}
18:24:57.626 Object {value: -20.959873329014293}
18:24:57.720 Object {value: -15.215298200036738}
18:24:57.742 Object {value: -13.990965698770527}
...
Run Code Online (Sandbox Code Playgroud)

我知道控制台在实验中增加了偏差,但我们仍然可以看到不同滴答时间之间存在一些很大的时间差异,这里约为 400 毫秒(您可以在屏幕上明确地看到发生的情况):

18:24:57.235 Object {value: -38.74063147167402}
18:24:57.626 Object {value: -20.959873329014293}
Run Code Online (Sandbox Code Playgroud)

与看起来正常的 ~20ms 相比(60FPS 应导致每个刻度之间的 ~17ms):

18:24:57.157 Object {value: -39.919418166496385}
18:24:57.175 Object {value: -39.76205524921881}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,当我以其他方式制作动画时,一切都很好。同样奇怪的是,我使用相同的动画(实际上是相同的代码)来为不同的对象设置动画,有些效果很好(增加和减少)。

为了比较,这里是递减部分:

18:24:55.541 Object {value: -1.124358489855093}
18:24:55.566 Object {value: -1.804371440300843}
18:24:55.592 Object {value: -3.0104530710073063}
18:24:55.607 Object {value: -3.896255056788916}
18:24:55.630 Object {value: -5.484551217549029}
18:24:55.661 Object {value: -7.919857696074535}
18:24:55.691 Object {value: -10.712999608975895}
18:24:55.707 Object {value: -12.43977121139206}
18:24:55.725 Object {value: -14.376069524734937}
18:24:55.743 Object {value: -16.422698462753544}
18:24:55.763 Object {value: -18.833926735827166}
18:24:55.796 Object {value: -23.027717951856513}
18:24:55.832 Object {value: -27.17280894556397}
18:24:55.865 Object {value: -30.581203230966732}
18:24:55.893 Object {value: -33.16734858413125}
18:24:55.908 Object {value: -34.426713502779336}
18:24:55.928 Object {value: -35.95476927982921}
18:24:55.957 Object {value: -37.822663476915075}
18:24:55.992 Object {value: -39.40622189728781}
18:24:56.007 Object {value: -39.80367046402294}
18:24:56.030 Object {value: -40}
Run Code Online (Sandbox Code Playgroud)

两帧之间的最大持续时间看起来约为 40 毫秒。


解决方案

我想我找到了造成这种情况的原因,我有一个巨大的组件在动画发生时正在更新。我认为这导致 JS 有更多的工作要做,我想这给安排动画事件的机会减少了。我不确定它内部是如何工作的,但可能有一个事件循环(和一个执行线程) )并且当另一个例程(这里是我的重组件的更新方法)正在运行时,动画步骤不会执行。

您有两种解决方案:

  1. 检查与动画并行发生的更新,并通过定义shouldComponentUpdate(nextProps, nextState)您认为导致 JS 速度减慢的任何组件来防止更新发生。
  2. 按照本文建议使用本机驱动程序:Dropping JS thread FPS because of do a lot of work on the JavaScript thread at the same time