iT邦幫忙

2024 iThome 鐵人賽

DAY 18
0

題目

CSS Challenge Day10
https://ithelp.ithome.com.tw/upload/images/20240929/20169403AgekjvrINI.png

上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。

我做好的此題CSS Challeage解答

那麼我們就開始吧。

題目分析

這個題目要求我們製作一個手錶的錶面

  1. 手錶的錶面本身
  2. 時間資訊:顯示基本的日期跟時間。
  3. 錶面資訊:左下角心跳,右下角是卡路里
  4. 圓點點裝飾
  5. 紅色順時針動畫

前情提要

我們上次已經完成了錶面上的基礎資訊,也改成使用 JS 來抓取當前的時間了,最後的完成畫面長這樣:
https://ithelp.ithome.com.tw/upload/images/20240930/201694039J896Tj8Bl.png
今天我們就來制作錶外面的兩個圈圈。
一個是由白色點點組成的圓圈,一個是紅色的順時針動畫

開始解題

白點點組成的圓圈

HTML 架構

.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 個。
https://ithelp.ithome.com.tw/upload/images/20241001/20169403OsaAlhzFzR.png

樣式

$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 來對每個元素進行動態設置。具體說明如下:

位置:topleft 位置都使用了變數 $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點,共四個地方。

這樣白色圓點點繪製成的圈圈就完成了:
https://ithelp.ithome.com.tw/upload/images/20241001/20169403PYsxVmQKsp.png


紅色的順時針動畫

HTML

.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);
	}
}

詳細說明如下:

  1. .spinner

    • $spinnerWH: $roundWH - 10:這邊要算出紅色圓形動畫的寬高,於是就把錶面的寬高拿來減少一點,左右各 5 的話就是減 10。
    • 擴展 .center:以確保圓形在頁面中居中定位。
    • 寬高設置:使用變數 $spinnerWH 來控制 spinner 的寬度和高度。
  2. circle

    • stroke 設置為紅色,並使用 stroke-dasharray: 625 來定義畫線的長度。
    • animation 使用 animate-spinner,持續 5 秒,以線性且無限的方式運行。
    • 圓形會從 -90 度開始旋轉,並通過 transform-origin: center 保持旋轉中心。

Wrap up and go home

希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。

那今天就先到這裡,明天我們再繼續來玩下一集。


上一篇
Day 17 - CSS Challenge #10:Watch UI(上)
下一篇
Day 19 - CSS Challenge #11:Walking Boots(上)
系列文
Dive into CSS Challenge:從問題到解決方案的實踐之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言