用 CSS 製作 Pie Chart 且頁面下滑觸發動畫效果
以往製作像這樣的 Pie Chart,都使用第三套件或 SVG。這次想使用單純的 HTML & CSS 來挑戰看看。
這裡僅描述幾個重點的地方,若想看原始碼,可參考下方的「下載原始碼」喔。
先看看以下的完成結果:
Pie Chart - HTML
在 HTML 的部份,非常簡單,我們只要需要一個標籤即可:
<div class="pie ani" style="--percentage: 30; --color: purple;">30%</div>
- ani 這個 class 是為了觸發動畫效果而寫的 class,如果不想要動畫效果的話,此 class 可以不用加。
- 設定了兩個變數,分別是 --percentage(0 ~ 100 的百分比) 和 --color(圓圈的顏色)。
Pie Chart - CSS
然而 CSS 的部份,主要使用了 conic-gradient 和 radial-gradient 兩種漸層模式,然後使用 mask 遮罩效果。基本上就大致完成了。
動畫效果就單純使用 animation 相關的 CSS,且寫在 ani 這個 class,然後 @keyframes 用來設定變數 --percentage 做動畫效果。
比較需要留意的一點是 @property,並不是每個瀏覽器都支援,所以若遇到不支援的瀏覽器,那就不會有動畫效果的產生了。但至少整個的 Pie Chart 還是有正常呈現。
* {
box-sizing: border-box;
}
/* 自訂屬性,留意支援程度: https://caniuse.com/?search=%40property */
@property --percentage{
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@keyframes pieAni {
from {
--percentage: 0;
}
}
.pie {
width: 150px;
/* 寬高比 1:1 */
aspect-ratio: 1;
display: inline-grid;
place-content: center;
margin: 5px;
font-size: 25px;
font-weight: bold;
font-family: sans-serif;
position: relative;
}
.pie::before{
content: "";
display: inline-block;
position: absolute;
border-radius: 50%;
/* 等同於 top、right、bottom、left 皆設定 0 */
inset: 0;
/* conic-gradient 線上資源: https://www.w3schools.com/css/css3_gradients_conic.asp */
background: conic-gradient(var(--color) calc(var(--percentage) * 1%),#0000 0%), #eee;
/* radial-gradient 線上資源: https://www.w3schools.com/cssref/func_radial-gradient.php */
/* mask 線上資源: https://www.w3schools.com/css/css3_masking.asp */
/* mask 相關屬性,在 Chrome, Edge 需使用 -webkit- 前綴才支援 */
-webkit-mask-image: radial-gradient(farthest-side,#0000 calc(100% - 10px),#000 calc(100% - 10px));
mask-image: radial-gradient(farthest-side,#0000 calc(100% - 10px),#000 calc(100% - 10px));
}
.pie.ani{
animation-name: pieAni;
animation-duration: 2s;
animation-fill-mode: both;
}
Pie Chart - 撰寫 Vanilla JS,頁面往下滑,碰到 Pie Chart 時,才觸發動畫效果
有的時候,Pie Chart 並不在頁面的第一屏,是在第一屏以外的地方,這樣一進到頁面,跑動畫效果的話,其實沒什麼意義,所以應該要讓螢幕往下滑時, 螢幕的底部,碰到 Pie Chart 的頂部時,才觸發動畫效果,相關的 JS 如下:
function pieAnimation(){
// 找出 class 名稱有 pie,但不能有 ani 這個 class 的元素
let pie_el = document.querySelectorAll(".pie:not(.ani)");
pie_el.forEach((item, i) => {
//console.log( item.getBoundingClientRect().top - window.innerHeight );
// d: 螢幕的底部 到 圓圈的頂部 的距離
let d = item.getBoundingClientRect().top - window.innerHeight;
if(d < 0){
item.classList.add("ani");
}
});
}
window.addEventListener("scroll", () => {
pieAnimation();
});
結果畫面
這裡示範一下,也可以直接按下按鈕,觸發動畫效果。(註:Chrome 和 Edge 瀏覽器才支援)
60%