圆点加载动画 ( 阴影动画 )
这个范例教学会使用 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 处理会更有效率,不过这篇范例的重点是在于多重阴影、多重动画、自订属性的互相搭配,只要熟练运用,就能做出许多有趣的效果。
微信扫码关注
抖音扫码关注