CSS 製作圓點載入動畫 ( 陰影動畫 )
這個範例教學會使用 CSS box-shadow 的陰影樣式,讓單一個 div 的多重陰影在畫面中產生十六個圓點,並搭配自訂屬性 @property 和動畫 animation 讓陰影動起來,實作漂亮的圓點載入動畫。
快速導覽:
多重陰影產生十六個圓點
在 box-shadow
陰影樣式屬性撰寫多種陰影樣式,就能做出多重陰影的效果,運用三角函數公式,就能將這些陰影定位在一個圓的圓周上,舉例來說,當一個圓的半徑為 50px,就能產生下方的座標點:
(50px, 0px)
(46.20px, 19.14px) // 50px * cos(22.5deg), 50px * sin(22.5deg)
(35.36px, 35.36px) // (50px * cos(45deg), 50px * sin(45deg))
(19.14px, 46.20px) // (50px * cos(67.5deg), 50px * sin(67.5deg))
(0px, 50px)
(-19.14px, 46.20px) // 50px * cos(112.5deg), 50px * sin(112.5deg)
(-35.36px, 35.36px) // 50px * cos(135deg), 50px * sin(135deg)
(-46.20px, 19.14px) // 50px * cos(157.5deg), 50px * sin(157.5deg)
(-46.20px, -19.14px) // 50px * cos(202.5deg), 50px * sin(202.5deg)
(-35.36px, -35.36px) // 50px * cos(225deg), 50px * sin(225deg)
(-19.14px, -46.20px) // 50px * cos(247.5deg), 50px * sin(247.5deg)
(0px, -50px)
(19.14px, -46.20px) // 50px * cos(292.5deg), 50px * sin(292.5deg)
(35.36px, -35.36px) // 50px * cos(315deg), 50px * sin(315deg)
(46.20px, -19.14px) // 50px * cos(337.5deg), 50px * sin(337.5deg)
將這些座標點改成 CSS 的寫法,使用透明色隱藏元素本身,畫面中就會出現十六個透過陰影產生的圓點。
<!-- HTML 程式碼 -->
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
.c {
position: absolute;
top: 100px;
left: 100px;
width: 10px;
height: 10px;
background: #0000; /* 元素本身透明 */
border-radius: 50%; /* 圓角產生圓形,影子才會是圓形 */
/* 多重陰影 */
box-shadow:
#f00 50px 0 0 0,
#f00 46.19px 19.14px 0 0,
#f00 35.36px 35.36px 0 0,
#f00 19.14px 46.19px 0 0,
#f00 0 50px 0 0,
#f00 -19.14px 46.19px 0 0,
#f00 -35.36px 35.36px 0 0,
#f00 -46.19px 19.14px 0 0,
#f00 -50px 0 0 0,
#f00 -46.19px -19.14px 0 0,
#f00 -35.36px -35.36px 0 0,
#f00 -19.14px -46.19px 0 0,
#f00 0 -50px 0 0,
#f00 19.14px -46.19px 0 0,
#f00 35.36px -35.36px 0 0,
#f00 46.19px -19.14px 0 0;
}
</style>
使用 @property 和 animation 讓陰影動起來
如果要在 CSS 的陰影無法使用基本的方法套用動畫效果 ( 類似漸層色無法直接套用動畫效果 ),必須使用「自訂屬性 @property」,透過改變屬性值的方式產生動畫,下方範例會新增一個 --c
自訂屬性,並將陰影的「尺寸」換成 var(--c)
,透過改變自訂屬性的方式讓圓點出現和消失。
<!-- HTML 程式碼 -->
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
@property --c {
syntax: "<length>"; /* 自訂屬性類型是長度 */
inherits: true;
initial-value: -5px; /* 自訂屬性預設值為 -5px */
}
.c {
position: absolute;
width: 10px;
height: 10px;
background: #0000;
border-radius: 50%;
top: 100px;
left: 100px;
/* 陰影尺寸都改成 var(--c) 讀取自訂屬性 */
box-shadow:
#f00 50px 0 0 var(--c),
#f00 46.19px 19.14px 0 var(--c),
#f00 35.36px 35.36px 0 var(--c),
#f00 19.14px 46.19px 0 var(--c),
#f00 0 50px 0 var(--c),
#f00 -19.14px 46.19px 0 var(--c),
#f00 -35.36px 35.36px 0 var(--c),
#f00 -46.19px 19.14px 0 var(--c),
#f00 -50px 0 0 var(--c),
#f00 -46.19px -19.14px 0 var(--c),
#f00 -35.36px -35.36px 0 var(--c),
#f00 -19.14px -46.19px 0 var(--c),
#f00 0 -50px 0 var(--c),
#f00 19.14px -46.19px 0 var(--c),
#f00 35.36px -35.36px 0 var(--c),
#f00 46.19px -19.14px 0 var(--c);
animation: oxxo 1s alternate infinite; /* 重複不斷播放 */
}
/* 動畫改變自訂屬性 */
@keyframes oxxo {
0% {--c: -5px;} /* -5px 為圓點大小 10px 的半徑 */
100% {--c: 0;}
}
</style>
使用動畫延遲,讓圓點依序出現
為了利用圓點「大小出現的時間差」產生「旋轉」效果,必須透過「動畫延遲」和「多重動畫」方式,讓每個圓點出現的時間有所不同並依序出現,修*改上述的範例程式碼,增加一些自訂屬性 ( 改成 --c1、--c2 等 ) 以及動畫影格名稱 ( oxxo1、oxxo2 等 ),並加入延遲時間,就能產生依序出現的效果,下方範例先修改四個圓點 ( 程式碼會開始大幅增加 )。
<!-- HTML 程式碼 -->
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
/* 自訂屬性 */
@property --c1 {
syntax: "<length>";
inherits: true;
initial-value: -5px;
}
@property --c2 {
syntax: "<length>";
inherits: true;
initial-value: -5px;
}
@property --c3 {
syntax: "<length>";
inherits: true;
initial-value: -5px;
}
@property --c4 {
syntax: "<length>";
inherits: true;
initial-value: -5px;
}
.c {
position: absolute;
width: 10px;
height: 10px;
background: #0000;
border-radius: 50%;
top: 100px;
left: 100px;
/* 注意自訂屬性名稱不同 */
box-shadow:
#f00 50px 0 0 var(--c1),
#f00 46.19px 19.14px 0 var(--c2),
#f00 35.36px 35.36px 0 var(--c3),
#f00 19.14px 46.19px 0 var(--c4),
#f00 0 50px 0 var(--c1),
#f00 -19.14px 46.19px 0 var(--c2),
#f00 -35.36px 35.36px 0 var(--c3),
#f00 -46.19px 19.14px 0 var(--c4),
#f00 -50px 0 0 var(--c1),
#f00 -46.19px -19.14px 0 var(--c2),
#f00 -35.36px -35.36px 0 var(--c3),
#f00 -19.14px -46.19px 0 var(--c4),
#f00 0 -50px 0 var(--c1),
#f00 19.14px -46.19px 0 var(--c2),
#f00 35.36px -35.36px 0 var(--c3),
#f00 46.19px -19.14px 0 var(--c4);
/* 多重動畫,每個動畫都增加 0.2s 延遲 */
animation: oxxo1 1s alternate infinite,
oxxo2 1s 0.2s alternate infinite,
oxxo3 1s 0.4s alternate infinite,
oxxo4 1s 0.6s alternate infinite;
}
/* 動畫影格名稱不同 */
@keyframes oxxo1 {
0% {--c1: -5px;}
100% {--c1: 0;}
}
@keyframes oxxo2 {
0% {--c2: -5px;}
100% {--c2: 0;}
}
@keyframes oxxo3 {
0% {--c3: -5px;}
100% {--c3: 0;}
}
@keyframes oxxo4 {
0% {--c4: -5px;}
100% {--c4: 0;}
}
</style>
圓點載入動畫 ( 使用 JavaScript 簡化程式碼 )
因為透過多重陰影產生的動畫需要撰寫「大量又類似」的 CSS 程式碼,為了縮減程式碼長度,可以透過 JavaScript 將重複的部分獨立出來,並運用迴圈替換變數,後續也比較方便修改調整,如果要做得更有彈性,連同陰影的顏色和陰影位置都能運用 JavaScript 來調整,詳細說明可以參考下方範例:
<!-- HTML 程式碼 -->
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
/* 將重複的程式碼全部交由 JS 處裡 */
.c {
position: absolute;
width: 10px;
height: 10px;
background: #0000;
border-radius: 50%;
top: 100px;
left: 100px;
}
</style>
<!-- JavaScript 程式碼 -->
<script>
const head = document.head; // 取得頁面的 head 區塊
const style = document.createElement('style'); // 建立一個新的 style 區塊
head.appendChild(style); // head 區塊中加入 style
let cssProperty = ''; // CSS 自訂屬性和影格內容
let anime = ''; // CSS 動畫
let boxShadow = ''; // CSS 陰影
let color = 'red'; // 圓點顏色
let radius = 50; // 繞圓的半徑
let num = 16; // 圓的數量
let deg = ~~(360/num*10)/10; // 根據數量計算角度,取值到小數點第二位
let cr = 10; // 小圓點半徑
// 建立函式,根據角度計算位置
function pos(angle, r){
let rad = angle*Math.PI/180; // 換算弧度
let px = Math.cos(rad)*r; // x 座標
let py = Math.sin(rad)*r; // y 座標
return [px, py]; // 回傳陣列結果
}
// 使用迴圈,產生每個點的自訂屬性和動畫影格名稱
for(let i=1; i<num+1; i++){
let c = `
@property --c${i} {
syntax: "<length>";
inherits: true;
initial-value: -${cr}px;
}
@keyframes oxxo${i} {
0% {--c${i}: -${cr}px;}
100% {--c${i}: 0;}
}`;
let xy = pos((i-1)*deg, radius); // 透過函式取得 xy 座標
let x = ~~(xy[0]*100)/100; // x 座標,取值到小數點第二位
let y = ~~(xy[1]*100)/100; // y 座標,取值到小數點第二位
let sec = ~~((i-1)*0.2*10)/10; // 延遲秒數,取值到小數點第一位,處理 JS 很多的小數點問題
anime = anime + `oxxo${i} 1s ${sec}s alternate infinite,`; // 動畫 CSS
boxShadow = boxShadow + `${color} ${x}px ${y}px 0 var(--c${i}),`; // 陰影 CSS
cssProperty = cssProperty + c; // 組合 CSS
}
anime = anime.replace(/.$/,';'); // 替換最後的 , 為 ;
boxShadow = boxShadow.replace(/.$/,';'); // 替換最後的 , 為 ;
cssProperty = cssProperty + `.c {animation: ${anime} box-shadow: ${boxShadow} }`; // 組合 CSS
style.appendChild(document.createTextNode(cssProperty)); // 添加 CSS
</script>
小結
CSS 的圓點載入動畫其實不複雜,只是程式碼多了點 ( 大多都是重複撰寫 ),單純透過 CSS 也可以實現,只是為了減少重複的程式碼,使用 JavaScript 處理會更有效率,不過這篇範例的重點是在於多重陰影、多重動畫、自訂屬性的互相搭配,只要熟練運用,就能做出許多有趣的效果。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~