Day18 純 CSS DVD 反彈動畫
今天我們要使用純 CSS 實現 DVD 反彈動畫,讓大家認識 steps()
以及 animation-composition
屬性的使用方式,並提供這個實用的應用。(應該吧...)
HTML
HTML,簡單
1<div></div>
CSS
版面
CSS 我們先不放背景圖片,用正方形就好了。用這種深藍色整個味道都出來了 XD。<body>
設定 overflow: hidden;
是因為有時候反彈時會撞出滾動條,看起來不是很舒服。
1body {
2 background: #000;
3 overflow: hidden;
4}
5
6div {
7 width: 100px;
8 height: 100px;
9 background: blue;
10}
動畫
我們分析一下,DVD 反彈動畫需要的動畫
- 水平移動 -
translateX()
- 垂直移動 -
translateY()
- 水平碰撞時改變顏色
- 垂直碰撞時改變顏色
移動動畫
我們先來實現水平移動,我們使用 translateX()
來實現,並且使用 animation
屬性來實現動畫。因為元素定位點是在左上角,所以我們需要記得移動到 100vw - 100%
的位置就可以了。
transform:translate()
的百分比是相對於自己的寬高計算的,所以我們可以使用100%
來表示自己的寬高。
1@keyframes horizontal {
2 from {
3 transform: translateX(0);
4 }
5 to {
6 transform: translateX(calc(100vw - 100%));
7 }
8}
OK 沒問題。那垂直的也加上去。兩個時間故意設定稍微不一樣,讓路線隨機一點。
1div {
2 width: 100px;
3 height: 100px;
4 background: blue;
5 animation:
6 horizontal 2.6s infinite linear alternate,
7 vertical 2s infinite linear alternate;
8}
9
10@keyframes horizontal {
11 from {
12 transform: translateX(0);
13 }
14 to {
15 transform: translateX(calc(100vw - 100%));
16 }
17}
18@keyframes vertical {
19 from {
20 transform: translateY(0);
21 }
22 to {
23 transform: translateY(calc(100vh - 100%));
24 }
25}
欸等等,垂直移動效果加上去之後,水平移動的效果就沒了!因為兩個都是使用 transform
屬性,所以其中一個被蓋過去了。但我們的動畫是要同時執行,變色動畫都還沒加上去啊!在之前常見的解決方法有
- 使用
top
、left
屬性代替transform
屬性 - 外面再包一層
div
,讓 兩個div
同時移動
而今天我們有一個更加優雅的解決方法,就是使用 animation-composition
屬性,讓兩個動畫同時執行。我們給 div
加上 animation-composition
屬性,並且設定 accumulate
值。
1animation-composition: accumulate;
呼~救回來了,但是我們的動畫還沒有變色,我們來加上變色的動畫。
變色動畫
我們使用 filter
屬性來實現,filter
屬性有一個 hue-rotate()
函式,可以讓顏色旋轉,我們使用 hue-rotate(360deg)
來讓顏色旋轉一圈,就可以讓顏色變回原本的顏色了,讓所有顏色都可以跑過一次。
顏色改變的動畫長度記得要是平移動畫長度的倍數,才可以在撞牆時剛好變色。
1div {
2 /* 同上 */
3 animation:
4 horizontal 2.6s infinite linear alternate,
5 vertical 2s infinite linear alternate,
6 colorX 26s infinite,
7 colorY 14s infinite;
8 animation-composition: accumulate;
9}
10
11@keyframes colorX {
12 to {
13 filter: hue-rotate(360deg);
14 }
15}
16@keyframes colorY {
17 to {
18 filter: hue-rotate(360deg);
19 }
20}
怎麼說呢,顏色是漸漸變而不是直接變,這樣看起來就不是很像 DVD 動畫了。而這個時候我們就要拿出 step()
。steps()
是一個可以讓動畫在指定時間內,依照指定的步數來執行的函式,而不是漸變。中間可以填入數字代表中間要經過幾個顏色。
1animation:
2 horizontal 2.6s infinite linear alternate,
3 vertical 2s infinite linear alternate,
4 colorX 26s infinite steps(10),
5 colorY 14s infinite steps(7);
DVD 圖片
最後換成 DVD 的圖片。從維基百科抓 svg 向量圖...結果...
甚麼都看不到。原因是 Logo 的背景是黑色的。你可以使用我製作的這個圖示上色 CSS 濾鏡生成器,透過 filter
屬性來改變 Logo 的顏色。把它貼上到動畫中,並在後面的hue-rotate()
屬性中加上 360 度就可以囉。
1@keyframes colorX {
2 from {
3 filter: invert(9%) sepia(84%) saturate(5931%) hue-rotate(245deg)
4 brightness(116%) contrast(153%);
5 }
6 to {
7 filter: invert(9%) sepia(84%) saturate(5931%) hue-rotate(605deg)
8 brightness(116%) contrast(153%);
9 }
10}
成果如下
https://codepen.io/edit-mr/pen/abPjjMd
1<img src="https://upload.wikimedia.org/wikipedia/commons/9/9b/DVD_logo.svg" />
1body {
2 background: #000;
3 overflow: hidden;
4}
5
6img {
7 width: 100px;
8 animation:
9 horizontal 2.6s infinite linear alternate,
10 vertical 2s infinite linear alternate,
11 colorX 26s infinite steps(10),
12 colorY 14s infinite steps(7);
13 animation-composition: accumulate;
14}
15@keyframes horizontal {
16 from {
17 transform: translateX(0);
18 }
19 to {
20 transform: translateX(calc(100vw - 100%));
21 }
22}
23@keyframes vertical {
24 from {
25 transform: translateY(0);
26 }
27 to {
28 transform: translateY(calc(100vh - 100%));
29 }
30}
31@keyframes colorX {
32 from {
33 filter: invert(9%) sepia(84%) saturate(5931%) hue-rotate(245deg)
34 brightness(116%) contrast(153%);
35 }
36 to {
37 filter: invert(9%) sepia(84%) saturate(5931%) hue-rotate(605deg)
38 brightness(116%) contrast(153%);
39 }
40}
41@keyframes colorY {
42 from {
43 filter: invert(9%) sepia(84%) saturate(5931%) hue-rotate(245deg)
44 brightness(116%) contrast(153%);
45 }
46 to {
47 filter: invert(9%) sepia(84%) saturate(5931%) hue-rotate(605deg)
48 brightness(116%) contrast(153%);
49 }
50}
以上就是我今天的分享,歡迎在 Instagram 和 Google 新聞追蹤毛哥EM資訊密技,也歡迎訂閱我新開的YouTube 頻道:網棧。
我是毛哥EM,讓我們明天再見。