上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
這個題目要求我們製作一個手錶的錶面
我們上次已經完成了錶面上的基礎資訊,也改成使用 JS 來抓取當前的時間了,最後的完成畫面長這樣:
今天我們就來制作錶外面的兩個圈圈。
一個是由白色點點組成的圓圈,一個是紅色的順時針動畫
.frame
.center
// --新增的地方
- for i in (1..15)
div class="dotted-group-#{i}"
- for i in (1..4)
div class="dotted-#{i}"
// --新增的地方
.text
...
首先說明一下這段白色點點組成的圓圈要怎麼畫:
這段的概念是,我在畫面上 3點、6點、9點、12點的地方,各產生一個內部 div
取名為 .dotted-#{i}
,之後我們會再用 CSS 把它們繪製成白色點點的樣子。在這邊我們只要先有概念,先把版開出來就好。
然後再用一個取名為 .dotted-group-#{i}
的 div
把這 4 個 div
包起來,然後將他重複制作 15 個,之後我們再使用 CSS 來旋轉他,從 0 分轉到 15 分,四分之一圈,因為我們有四個點點,就可以形成一個由白色點點組成的圓。
說明如下:
for i in (1..15)
:生成15個 .dotted-group
元素。每個 group
包含數個點。
內部循環 - for i in (1..4)
:在每個 .dotted-group
中生成4個 .dotted
點。
如果你只有 1 個的話會長這樣,但在這邊我們就是畫出 15 個並讓它旋轉。
簡單說就是時鐘刻度 00 分到 15 分的距離,所以畫出 15 個。
$dottedWH: 172px;
$dottedLT: ($roundWH - $dottedWH) / 2;
@for $i from 1 through 15 {
.dotted-group-#{$i} {
position: absolute;
top: $dottedLT;
left: $dottedLT;
border-radius: 100%;
width: $dottedWH;
height: $dottedWH;
transform: rotate((($i - 1) * 6) + deg ) ;
}
這段 CSS 使用了 @for
迴圈來生成 15 個 .dotted-group
元素,並且通過變數 $i
來對每個元素進行動態設置。具體說明如下:
位置:top
和 left
位置都使用了變數 $dottedLT
來動態設置。
形狀:每個元素都是圓形,因為使用了 border-radius: 100%
。
寬高:使用變數 $dottedWH
設定了每個圓形的寬度和高度。
旋轉:通過 transform: rotate()
,將每個元素按其順序乘以 6 度進行旋轉,創造環狀分佈的效果。
接著來畫裡面的四個小點
@for $i from 1 through 15 {
.dotted-group-#{$i} {
...
.dotted {
&-1 {
position: absolute;
transform: translate(-50%, -50%);
left: 50%;
width: 2px;
height: 2px;
background: #fff;
border-radius: 100%;
}
&-2 {
@extend .dotted-1;
left: 100%;
top: 50%;
}
...
}
}
}
}
這段的具體說明如下:
position: absolute
:這樣可以讓元素相對於其最近的定位祖先元素進行自由定位。transform: translate(-50%, -50%)
:將元素的中心點精確對齊於 left: 50%
所設定的參考位置,使其水平居中。left: 50%
:將元素的左邊對齊容器的正中間。width: 2px; height: 2px;
:設定元素的大小為 2px 的正方形。background: #fff
:設置背景顏色為白色。border-radius: 100%
:使這個小正方形變成圓形。.dotted-2
擴展了 .dotted-1
的樣式,也就是他會繼承 dotted-1
所有的樣式,再使用 left: 100%
top: 50%
將圓點定位在容器的右邊中心。
其餘的兩個點也都是修改定位點,去讓位置在剛剛說的3點、6點、9點、12點,共四個地方。
這樣白色圓點點繪製成的圈圈就完成了:
.frame
.center
// --新增的地方
svg.spinner viewBox="0 0 202 202"
circle cx="101" cy="101" r="99.5"
// --新增的地方
...
先把要旋轉的 SVG 放上去。
這邊我是使用題目的 codepen 裡面提供的 SVG,當然你要嘗試自己繪製也可以。
這段 HTML 代碼定義了一個 svg
元素作為 "spinner" 動畫的容器,並繪製一個圓形:
svg.spinner
: 定義了一個大小為 202x202 的 SVG 畫布,使用 viewBox="0 0 202 202"
來設置畫布的視口。
circle
: 則是繪製一個圓形,圓心座標為 (101, 101)
,半徑為 99.5
,剛好位於 SVG 畫布的中心。這種結構常用於動畫或圖形繪製。
@keyframes animate-spinner {
0% {
stroke-dashoffset: 625;
transform: rotate(-90deg) scaleY(1);
}
50% {
stroke-dashoffset: 0;
transform: rotate(-90deg) scaleY(1);
}
50.001% {
transform: rotate(-90deg) scaleY(-1);
}
100% {
stroke-dashoffset: 625;
transform: rotate(-90deg) scaleY(-1);
}
}
這段 @keyframes animate-spinner
是用來控制 SVG 圓形動畫的:
stroke-dashoffset
:在 0% 時設為 625,代表畫線的起點偏移,隨著動畫進行,50% 時變為 0,圓圈完成繪製,100% 又回到 625。
transform
:讓圓形進行旋轉和垂直方向的縮放。旋轉角度保持 -90 度,從 50.001% 開始,scaleY(-1) 反轉垂直方向,形成來回翻轉效果。
這樣就會形成好像本來繞一圈的時候,紅色圈圈長出來,繞第二圈的時候,紅色圈圈消失的畫面。
動畫繪製好之後,就套用到我們剛剛的 SVG 上。
$spinnerWH: $roundWH - 10;
.spinner {
@extend .center;
border: none;
background: none;
width: $spinnerWH;
height: $spinnerWH;
circle {
stroke: $red;
stroke-width: 3;
fill: none;
stroke-dasharray: 625;
animation: animate-spinner 5s linear infinite;
transform-origin: center center;
transform: rotate(-90deg);
}
}
詳細說明如下:
.spinner
:
$spinnerWH: $roundWH - 10
:這邊要算出紅色圓形動畫的寬高,於是就把錶面的寬高拿來減少一點,左右各 5 的話就是減 10。.center
:以確保圓形在頁面中居中定位。$spinnerWH
來控制 spinner 的寬度和高度。circle
:
stroke
設置為紅色,並使用 stroke-dasharray: 625
來定義畫線的長度。animation
使用 animate-spinner
,持續 5 秒,以線性且無限的方式運行。transform-origin: center
保持旋轉中心。希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。
那今天就先到這裡,明天我們再繼續來玩下一集。