K.W*_*.Wu 5 animation reactjs react-native
我在 a 上面写了一个粘性标题FlatList
,我有我想要的,看下面的图片,但是有两个问题。我想要的效果是:
首先图片的高度是170
当用户向上滚动时,图片也会向上滚动
但是当用户滚动 100 时,图片停止向上并停留在那里(意味着显示图片的底部 70)
同时,当用户滚动时,不透明度从 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
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 有更多的工作要做,我想这给安排动画事件的机会减少了。我不确定它内部是如何工作的,但可能有一个事件循环(和一个执行线程) )并且当另一个例程(这里是我的重组件的更新方法)正在运行时,动画步骤不会执行。
您有两种解决方案:
shouldComponentUpdate(nextProps, nextState)
您认为导致 JS 速度减慢的任何组件来防止更新发生。