• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# transform样式动画
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @CCFFWW-->
5<!--Designer: @yangfan229-->
6<!--Tester: @lxl007-->
7<!--Adviser: @HelloCrease-->
8
9设置transform属性对组件进行旋转、缩放、移动和倾斜。
10
11
12## 设置静态动画
13
14创建一个正方形并旋转90°变成菱形,并用下方的长方形把菱形下半部分遮盖形成屋顶,设置长方形translate属性值为(150px,-150px)确定坐标位置形成门,再使用position属性使横纵线跟随父组件(正方形)移动到指定坐标位置,接着设置scale属性使父子组件一起变大形成窗户大小,最后使用skewX属性使组件倾斜后设置坐标translate(200px,-710px)得到烟囱。
15
16```html
17<!-- xxx.hml -->
18<div class="container">
19  <div class="top"></div>
20  <div class="content"></div>
21  <div class="door"></div>
22  <!-- 窗户 -->
23  <div class="window">
24    <div class="horizontal"></div>
25    <div class="vertical"></div>
26  </div>
27  <div class="chimney"></div>
28</div>
29```
30
31```css
32/* xxx.css */
33.container {
34  width:100%;
35  height:100%;
36  background-color:#F1F3F5;
37  align-items: center;
38  flex-direction: column;
39}
40.top{
41  z-index: -1;
42  position: absolute;
43  width: 428px;
44  height: 428px;
45  background-color: #860303;
46  transform: rotate(45deg);
47  margin-top: 284px;
48  margin-left: 148px;
49}
50.content{
51  margin-top: 500px;
52  width: 600px;
53  height: 400px;
54  background-color: white;
55  border:  1px solid black;
56}
57.door{
58  width: 100px;
59  height: 135px;
60  background-color: #1033d9;
61  transform: translate(150px,-137px);
62}
63.window{
64  z-index: 1;
65  position: relative;
66  width: 100px;
67  height: 100px;
68  background-color: white;
69  border: 1px solid black;
70  transform: translate(-150px,-400px) scale(1.5);
71}
72/* 窗户的横轴 */
73.horizontal{
74  position: absolute;
75  top: 50%;
76  width: 100px;
77  height: 5px;
78  background-color: black;
79}
80/* 窗户的纵轴 */
81.vertical{
82  position: absolute;
83  left: 50%;
84  width: 5px;
85  height: 100px;
86  background-color: black;
87}
88.chimney{
89  z-index: -2;
90  width: 40px;
91  height: 100px;
92  border-radius: 15px;
93  background-color: #9a7404;
94  transform: translate(200px,-710px) skewX(-5deg);
95}
96```
97
98![zh-cn_image_0000001220634677](figures/zh-cn_image_0000001220634677.png)
99
100
101## 设置平移动画
102
103小球下降动画,改变小球的Y轴坐标实现小球下落,在下一段时间内减小Y轴坐标实现小球回弹,让每次回弹的高度逐次减小直至回弹高度为0,就模拟出了小球下降的动画。
104
105```html
106<!-- xxx.hml -->
107<div class="container">
108  <div class="circle"></div>
109  <div class="flower"></div>
110</div>
111```
112
113```css
114/* xxx.css */
115.container {
116  width:100%;
117  height:100%;
118  background-color:#F1F3F5;
119  display: flex;
120  justify-content: center;
121}
122.circle{
123  width: 100px;
124  height: 100px;
125  border-radius: 50px;
126  background-color: red;
127  /* forwards停在动画的最后一帧 */
128  animation: down 3s fast-out-linear-in forwards;
129}
130.flower{
131  position: fixed;
132  width: 80%;
133  margin-left: 10%;
134  height: 5px;
135  background-color: black;
136  top: 1000px;
137}
138@keyframes down {
139  0%{
140    transform: translate(0px,0px);
141  }
142  /* 下落 */
143  15%{
144    transform: translate(10px,900px);
145  }
146  /* 开始回弹 */
147  25%{
148    transform: translate(20px,500px);
149  }
150  /* 下落 */
151  35%{
152    transform: translate(30px,900px);
153  }
154  /* 回弹 */
155  45%{
156    transform: translate(40px,700px);
157  }
158  55%{
159    transform: translate(50px,900px);
160  }
161  65%{
162    transform: translate(60px,800px);
163  }
164  80%{
165    transform: translate(70px,900px);
166  }
167  90%{
168    transform: translate(80px,850px);
169  }
170  /* 停止 */
171  100%{
172    transform: translate(90px,900px);
173  }
174}
175```
176
177![zh-cn_image_0000001174756438](figures/zh-cn_image_0000001174756438.gif)
178
179
180## 设置旋转动画
181
182设置不同的原点位置(transform-origin)改变元素所围绕的旋转中心。rotate3d属性前三个参数值分别为X轴、Y轴、Z轴的旋转向量,第四个值为旋转角度,旋转角度可为负值,负值则代表旋转方向为逆时针方向。
183
184```html
185<!-- xxx.hml -->
186<div class="container">
187  <div class="rotate">
188    <div class="rect rect1"></div>
189    <div class="rect rect2"></div>
190    <div class="rect rect3"></div>
191  </div>
192  <!-- 3d属性 -->
193  <div class="rotate3d">
194    <div class="content">
195        <div class="rect4"></div>
196        <div class="rect5"> </div>
197    </div>
198    <div class="mouse"></div>
199  </div>
200</div>
201```
202
203```css
204/* xxx.css */
205.container {
206    flex-direction: column;
207    background-color:#F1F3F5;
208    display: flex;
209    align-items: center;
210    justify-content: center;
211    width: 100%;
212    height: 100%;
213}
214.rect {
215    width: 100px;
216    height: 100px;
217    animation: rotate 3s infinite;
218    margin-left: 30px;
219}
220.rect1 {
221    background-color: #f76160;
222}
223.rect2 {
224    background-color: #60f76f;
225/* 改变原点位置*/
226    transform-origin: 10% 10px;
227}
228.rect3 {
229    background-color: #6081f7;
230/*  改变原点位置*/
231    transform-origin: right bottom;
232}
233@keyframes rotate {
234    from {
235        transform: rotate(0deg)
236    }
237    to {
238        transform: rotate(360deg);
239    }
240}
241/* 3d示例样式 */
242.rotate3d {
243    margin-top: 150px;
244    flex-direction: column;
245    background-color:#F1F3F5;
246    display: flex;
247    align-items: center;
248    width: 80%;
249    height: 600px;
250    border-radius: 300px;
251    border: 1px solid #ec0808;
252}
253.content {
254    padding-top: 150px;
255    display: flex;
256    align-items: center;
257    justify-content: center;
258}
259/* rect4 rect5 翻转形成眼睛 */
260.rect4 {
261    width: 100px;
262    height: 100px;
263    animation: rotate3d1 1000ms infinite;
264    background-color: darkmagenta;
265}
266.rect5 {
267    width: 100px;
268    height: 100px;
269    animation: rotate3d1 1000ms infinite;
270    margin-left: 100px;
271    background-color: darkmagenta;
272}
273.mouse {
274    margin-top: 150px;
275    width: 200px;
276    height: 100px;
277    border-radius: 50px;
278    border: 1px solid #e70303;
279    animation: rotate3d2 1000ms infinite;
280}
281/* 眼睛的动效 */
282@keyframes rotate3d1 {
283    0% {
284        transform:rotate3d(0,0,0,0deg)
285    }
286    50% {
287        transform:rotate3d(20,20,20,360deg);
288    }
289    100% {
290        transform:rotate3d(0,0,0,0deg);
291    }
292}
293/* 嘴的动效 */
294@keyframes rotate3d2 {
295    0% {
296        transform:rotate3d(0,0,0,0deg)
297    }
298    33% {
299        transform:rotate3d(0,0,10,30deg);
300    }
301    66% {
302        transform:rotate3d(0,0,10,-30deg);
303    }
304    100% {
305        transform:rotate3d(0,0,0,0deg);
306    }
307}
308```
309
310![zh-cn_image_0000001220316305](figures/zh-cn_image_0000001220316305.gif)
311
312> **说明:**
313>
314> transform-origin变换对象的原点位置,如果仅设置一个值,另一个值为50%,若设置两个值第一个值表示X轴的位置,第二个值表示Y轴的位置。
315
316
317## 设置缩放动画
318
319设置scale样式属性实现涟漪动画,先使用定位确定元素的位置,确定坐标后创建多个组件实现重合效果,再设置opacity属性改变组件不透明度实现组件隐藏与显示,同时设置scale值使组件可以一边放大一边隐藏,最后设置两个组件不同的动画执行时间,实现扩散的效果。
320
321设置scale3d中X轴、Y轴、Z轴的缩放参数实现动画。
322
323```html
324<!-- xxx.hml -->
325<div class="container">
326  <div class="circle">
327    <text>ripple</text>
328  </div>
329  <div class="ripple"></div>
330  <div class="ripple ripple2"></div>
331  <!-- 3d -->
332  <div class="content">
333    <text>spring</text>
334  </div>
335</div>
336```
337
338```css
339/* xxx.css */
340.container {
341    flex-direction: column;
342    background-color:#F1F3F5;
343    width: 100%;
344    position: relative;
345}
346.circle{
347    margin-top: 400px;
348    margin-left: 40%;
349    width: 100px;
350    height: 100px;
351    border-radius: 50px;
352    background-color: mediumpurple;
353    z-index: 1;  position: absolute;
354}
355.ripple{
356    margin-top: 400px;
357    margin-left: 40%;
358    position: absolute; z-index: 0;
359    width: 100px;
360    height: 100px;
361    border-radius: 50px;
362    background-color: blueviolet;
363    animation: ripple 5s infinite;
364}
365/* 设置不同的动画时间 */
366.ripple2{
367    animation-duration: 2.5s;
368}
369@keyframes ripple{
370    0%{
371        transform: scale(1);
372        opacity: 0.5;
373    }
374    50%{
375        transform: scale(3);
376        opacity: 0;
377    }
378    100%{
379        transform: scale(1);
380        opacity: 0.5;
381    }
382}
383text{
384    color: white;
385    text-align: center;
386    height: 100%;
387    width: 100%;
388}
389.content {
390    margin-top: 700px;
391    margin-left: 33%;
392    width: 200px;
393    height: 100px;
394    animation:rubberBand 1s infinite;
395    background-color: darkmagenta;
396    position: absolute;
397}
398@keyframes rubberBand {
399    0% {
400        transform: scale3d(1, 1, 1);
401    }
402    30% {
403        transform: scale3d(1.25, 0.75, 1.1);
404    }
405    40% {
406        transform: scale3d(0.75, 1.25, 1.2);
407    }
408    50% {
409        transform: scale3d(1.15, 0.85, 1.3);
410    }
411    65% {
412        transform: scale3d(.95, 1.05, 1.2);
413    }
414    75% {
415        transform: scale3d(1.05, .95, 1.1);
416    }
417    100%{
418        transform: scale3d(1, 1, 1);
419    }
420}
421```
422
423![zh-cn_image_0000001220396251](figures/zh-cn_image_0000001220396251.gif)
424
425> **说明:**
426>
427> 设置transform属性值后,子元素会跟着父元素一起改变,若只改变父元素其他属性值时(如:height,width),子元素不会改变。
428
429
430## 设置matrix属性
431
432matrix是一个入参为六个值的矩阵,6个值分别代表:scaleX, skewY, skewX, scaleY, translateX, translateY。下面示例中设置了matrix属性为matrix(1,0,0,1,0,200)使组件移动和倾斜。
433
434```html
435<!-- xxx.hml -->
436<div class="container">
437  <div class="rect"> </div>
438</div>
439```
440
441```css
442/* xxx.css */
443.container{
444  background-color:#F1F3F5;
445  display: flex;
446  justify-content: center;
447  width: 100%;
448  height: 100%;
449}
450.rect{
451  width: 100px;
452  height: 100px;
453  background-color: red;
454  animation: down 3s infinite forwards;
455}
456@keyframes down{
457  0%{
458    transform: matrix(1,0,0,1,0,0);
459  }
460  10%{
461    transform: matrix(1,0,0,1,0,200);
462  }
463  60%{
464    transform: matrix(2,1.5,1.5,2,0,700);
465  }
466  100%{
467    transform: matrix(1,0,0,1,0,0);
468  }
469}
470```
471
472![zh-cn_image_0000001174756580](figures/zh-cn_image_0000001174756580.gif)
473
474
475## 整合transform属性
476
477transform可以设置多个值并且多个值可同时设置,下面案例中展示同时设置缩放(scale),平移(translate),旋转(rotate)属性时的动画效果。
478
479```html
480<!-- xxx.hml -->
481<div class="container">
482  <div class="rect1"></div>
483  <div class="rect2"></div>
484  <div class="rect3"></div>
485  <div class="rect4"></div>
486  <div class="rect5"></div>
487</div>
488```
489
490```css
491/* xxx.css */
492.container{
493    width: 100%;
494    height: 100%;
495    flex-direction:column;
496    background-color:#F1F3F5;
497    padding:50px;
498}
499.rect1{
500    width: 100px;
501    height: 100px;
502    background-color: red;
503    animation: change1 3s infinite forwards;
504}
505.rect2{
506    margin-top: 50px;
507    width: 100px;
508    height: 100px;
509    background-color: darkblue;
510    animation: change2 3s infinite forwards;
511}
512.rect3{
513    margin-top: 50px;
514    width: 100px;
515    height: 100px;
516    background-color: darkblue;
517    animation: change3 3s infinite;
518}
519.rect4{
520    align-self: center;
521    margin-left: 50px;
522    margin-top: 200px;
523    width: 100px;
524    height: 100px;
525    background-color: darkmagenta;
526    animation: change4 3s infinite;
527}
528.rect5{
529    margin-top: 300px;
530    width: 100px;
531    height: 100px;
532   background-color: cadetblue;
533    animation: change5 3s infinite;
534}
535/* change1 change2 对比 */
536@keyframes change1{
537    0%{
538        transform: translate(0,0);    transform: rotate(0deg)
539    }
540    100%{
541        transform: translate(0,500px);
542        transform: rotate(360deg)
543    }
544}
545/* change2 change3 对比属性顺序不同的动画效果 */
546@keyframes change2{
547    0%{
548        transform:translate(0,0) rotate(0deg) ;
549    }
550    100%{
551        transform: translate(300px,0) rotate(360deg);
552    }
553}
554@keyframes change3{
555    0%{
556        transform:rotate(0deg) translate(0,0);
557    }
558    100%{
559        transform:rotate(360deg)  translate(300px,0);
560    }
561}
562/* 属性值不对应的情况 */
563@keyframes change4{
564    0%{
565        transform: scale(0.5);
566    }
567    100%{
568        transform:scale(2) rotate(45deg);
569    }
570}
571/* 多属性的写法 */
572@keyframes change5{
573    0%{
574        transform:scale(0) translate(0,0) rotate(0);
575    }
576    100%{
577        transform: scale(1.5) rotate(360deg) translate(200px,0);
578    }
579}
580```
581
582![zh-cn_image_0000001220554911](figures/zh-cn_image_0000001220554911.gif)
583
584> **说明:**
585> - 当设置多个transform时,后续的transform值会把前面的覆盖掉。若想同时使用多个动画样式可用复合写法,例:transform: scale(1) rotate(0) translate(0,0)。
586>
587> - transform进行复合写法时,变化样式内多个样式值顺序的不同会呈现不一样的动画效果。
588>
589> - transform属性设置的样式值要一一对应,若前后不对应,则该动画不生效。若设置多个样式值则只会呈现出已对应值的动画效果。
590
591
592## 相关实例
593
594针对transform样式动画开发,有以下相关实例可供参考:
595
596- [`JsClock`:时钟(JS)(API10)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/Solutions/Tools/JsClock)
597
598- [动画样式(JS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/JSUI/AnimationDemo)
599
600- [图片常见操作(JS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Media/ImageOperation)
601