让原生动画不顺畅

时间:2018-02-19 04:24:35

标签: reactjs animation react-native

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

  1. 首先,图片的高度为170

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

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

  4. 同时,当用户滚动

  5. 时,不透明度从最小值减少到0.5

    代码低于GIF

    enter image description here

    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;
    

    问题1

    动画不流畅

    问题2

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

1 个答案:

答案 0 :(得分:0)

我认为iPhone 6(真实设备)上的react-native: 0.55.4也有类似的问题。我试图将一个侦听器添加到动画值中,如下所示:

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}
...

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

18:24:57.235 Object {value: -38.74063147167402}
18:24:57.626 Object {value: -20.959873329014293}

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

18:24:57.157 Object {value: -39.919418166496385}
18:24:57.175 Object {value: -39.76205524921881}

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

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

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}

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


解决方案

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

您有两种解决方案:

  1. 检查与动画并行发生的更新,并在defining shouldComponentUpdate(nextProps, nextState)中阻止您认为导致JS速度降低的任何组件发生更新。
  2. 按照本文的建议使用本机驱动程序:Dropping JS thread FPS because of doing a lot of work on the JavaScript thread at the same time