requestAnimationFrame帧动画

前言

动画是移动应用中的一个相当重要的组成部分,一个用户体验良好的应用通常都具有流畅、有意义的动画。类似原生平台,React
Native也为我们提供了丰富的动画API:requestAnimationFrame、LayoutAnimation、Animated。

requestAnimationFrame:帧动画,是最容易实现的一种动画,通过不断改变组件的state值,从而在视觉上产生一种动画的效果,类似于gif动画的方式。

LayoutAnimation:布局动画,当布局发生改变时的动画模块,允许在全局范围内创建和更新动画,这些动画会在下一次渲染或布局周期运行,实现单个动画非常简洁,体验和性能良好。

Animated:用于创建更精细的交互控制的动画,可进行多个动画的组合动画,具备极高的性能,是功能最强大的动画API。

本节我们先介绍requestAnimationFrame。

requestAnimationFrame帧动画的实现

requestAnimationFrame实现帧动画的原理非常粗暴简洁,即通过修改state值来不断得改变视图上的样式,从而在视觉上产生一种动画的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
import React, { Component } from'react';



import {



AppRegistry,



StyleSheet,



Text,



View,



TouchableOpacity,



Platform,



} from'react-native';



exportdefaultclassFrameAnimationDemo extends Component {



constructor(props){



super(props);



this.state = {



width:200,



height:20,



};



}



_onPress() {



//每按一次增加近30宽高



varcount =0;



while(++count<30){



requestAnimationFrame(()={



this.setState({



width:this.state.width +1,



height:this.state.height +1



});



})



}



}



render() {



return(



<Viewstyle={styles.container}>




<Viewstyle={[styles.content,{width:this.state.width,height:this.state.height}]}>



<Textstyle={[{textAlign:'center'}]}>Hello World!</Text>



</View>



<TouchableOpacitystyle={styles.content}onPress={this._onPress.bind(this)}>



<Viewstyle={styles.button}>



<Textstyle={styles.buttonText}Press me!></Text>



</View>



</TouchableOpacity>



</View>



);



}



}



const styles = StyleSheet.create({



container: {



marginTop:25,



flex: 1,



},



content: {



backgroundColor: 'rgba(200, 230, 255, 0.8)',



marginBottom:10,



justifyContent:"center",



alignSelf:"center",



},



button: Platform.select({



ios: {},



android: {



elevation: 4,



// Material design blue from https://material.google.com/style/color.html
#color-color-palette



backgroundColor: '#2196F3',



borderRadius: 2,



width:100,



height:30,



},



justifyContent:"center",



alignSelf:"center",



}),



buttonText: {



alignSelf:"center",



}



});

从效果上看动画有种一顿一顿的感觉。这是由于通过修改state值,导致频繁地销毁、重绘视图,内存开销大,从而使得动画卡顿明显。另外对于帧动画而言,如果帧数较少,动画的效果会比较生硬,帧数过多又会引发性能问题。

优化

如果帧动画的方式更符合当前对动画的控制方式,我们可以对上述方法做一点优化,在requestAnimationFrame中采用setNativeProps直接修改组件的属性并触发局部刷新,不会导致重绘组件,因此在性能上优于直接修改state的方法。

修改_onPress方法,将对this.setState的直接修改改为对”Hello
World”按钮的属性修改this.refs.view1.setNativeProps。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
_onPress() {



varcount =0;



while(++count<30){



requestAnimationFrame(()={



this.refs.view1.setNativeProps({



style: {



width:this.state.width++,



height:this.state.height++



}



});



});



}



}

this.refs.view1指向的是”Hello World”文字的父视图。

1
2
3
4
5
6
7
8
9
10
<View ref="view1"style={[styles.content, {width:this.state.width,
height:this.state.height}]}>



<Textstyle={[{textAlign:'center'}]}>Hello World!</Text>



</View>

通过对比可以看出流畅顺滑多了。

每个动画API都有其适应和不适应的场景,如果要实现“弹性动画”,“缓入缓出”等效果,使用requestAnimationFrame还是比较难的,需要辅助各种函数。下一节将介绍另一种动画API——LayoutAnimation。

GitHub地址

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×