iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Modern Web

Dive into CSS Challenge:從問題到解決方案的實踐之旅系列 第 25

Day 25 - CSS Challenge #13:User Gallery(下)

  • 分享至 

  • xImage
  •  

題目

CSS Challenge Day13

  • Gallery
    https://ithelp.ithome.com.tw/upload/images/20241001/20169403lLGp6QVK44.png

題目除了基本 Gallery 介面樣式以外,還有點擊後的介面

  • Info
    https://ithelp.ithome.com.tw/upload/images/20241001/201694033LVKQfppCu.png

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

我做好的此題CSS Challeage解答

那麼我們就開始吧。

題目分析

這個題目要求我們製作一個 User Gallery

  1. 主頁面
    • 4 張照片組成
    • 滑鼠指上效果
      • 照片壓黑
      • 動態出現 [+] 的按鈕引導點擊。
  2. Info 頁面:
    • 上下開合的動畫來顯現info,動畫在背景、照片、關閉按鈕都有延遲。
    • 資訊區塊:照片與名稱
    • Action按鈕:下方三顆互動按鈕
    • 關閉按鈕:右上角關閉按鈕

前情提要

我們昨天已經把最開始的四格 User Gallery 跟滑鼠指上的效果都做出來了,也把點開的 info 頁面作了一半(如下圖),今天我們就來把最後的照片、右上角關閉按鈕、JS控制開關的部分、動畫都一次做完看看。
https://ithelp.ithome.com.tw/upload/images/20241004/20169403gXxWTeXM4I.png

開始解題

Info

bottom

照片

$profilePicWH: 100px;

.profile {
	z-index: 7;
	position: absolute;
	width: $profilePicWH;
	height: $profilePicWH;
	border-radius: 50%;
	top: 50%;
	left: 50%;
	border: 2px solid #fff;
	transform: translate3d(-50%,-69%,0);
	box-shadow: 4px 6px 15px 0 rgba(0,0,0,0.2);
	transition: all .6s ease-in-out .2s;
}

首先,一樣拿出第一天教的小工具尺規,來量一下照片的寬高,我這邊把它存在變數 $profilePicWH 裡面,再來就是依照題目的樣式來設定,具體如下:

  • 定位與尺寸:

    • position: absolute top: 50% left: 50%:將 .profile 定位在父容器的中心位置。
    • widthheight 使用變數 $profilePicWH 設置圖片的寬高。
    • transform: translate3d(-50%, -69%, 0):水平方向居中,垂直方向向上偏移 69%。這是最後的樣子,我們之後要跟 .active 內的樣子對調,總之先把它寫起來。
  • 外觀樣式:

    • border-radius: 50:設置圖片為圓形。
    • border: 2px solid #fff:加上 2px 白色實線邊框。
    • box-shadow: 4px 6px 15px 0 rgba(0,0,0,0.2):設置陰影。
    • transition: all .6s ease-in-out .2s:在 0.6 秒內過渡,延遲 0.2 秒開始變化。
      做好後長這樣:
      https://ithelp.ithome.com.tw/upload/images/20241004/20169403GRcMUHdm59.png

右上角關閉按鈕

.close {
	width: $plusIconWH;
	height: $plusIconWH;
	z-index: 8;
	position: absolute;
	right: 10px;
	top: 10px;
	border-radius: 50%;
	transition: transform .5s ease-in;
	transform: translate3d(0,0,0);
}

先做好按鈕的基本設定,顏色,寬高,圓角,也加上漸變一定要有的 transition

這裡需要注意的地方是,這顆按鈕其實有兩個動態效果,一個是滑鼠指上的時候底色跟上面"x"的顏色改變,另一個是點擊 gallery 或 click 按鈕本身時,觸發的顯示/隱藏 info 的動畫。由於這兩個效果的秒數不一樣,所以在這邊我們的 transition 也要分兩種來寫,一個放在按鈕上,這是管理他飛入飛出的,另一個放在 :afetr 上,這是管理滑鼠指上的。

然後這邊我們也先把 transform 的最終樣子寫上去,接著來設定裡面的"+"符號。

.close {
    &:after {
        content: '+';
		position: absolute;

		background: $primary;
		width: $plusIconWH;
		height: $plusIconWH;
		border-radius: 50%;
		font-size: 30px;
		line-height: .8;
		font-weight: 400;

		display: inline-flex;
		justify-content: center;
		align-items: center;
				
		transform: rotate(45deg);
		cursor: pointer;
        transition: background .3s ease-in-out;
	}
	&:hover:after {
		background-color: #fff;
		color: $primary;
	}
}

這邊絕大多數的 code 都是從上集的 plus icon 偷來的~因為幾乎是一樣的東西,差異只在於,這邊我們要把這個"+"旋轉個 45 度,讓它變成一個"x",這樣就好囉。
https://ithelp.ithome.com.tw/upload/images/20241004/201694038qM9sg6ASy.png


動畫部分

JS import

因為需要使用 JS 來寫 click 事件,所以我這邊還是引用了 css challenge 官方的 JS 來做使用,當然你也可以用你自己喜歡的。
https://ithelp.ithome.com.tw/upload/images/20241004/20169403haFThjwDFt.png

CSS設定位移

.info {
    &.active {
		pointer-events: all;
		
		.header, .bottom {
			transform: translate3d(0,0,0);
			transition: all .6s ease-in;
		}
		.profile {
			transform: translate3d(-50%,-69%,0);
			transition: all .8s ease-in-out .4s;
		}
		.close {
			transform: translate3d(0,0,0);
			transition: transform .5s ease-in .8s;
		}
	}
}

前面我們有先設定了 .info 裡面的 .active,那麼我們現在就把剛剛幾個需要動畫的物件內,我們剛剛設定好的最後位置樣式,複製到 .active 裡面。這邊要記得把 transition 也複製過來,這樣當我們要從 .active 離開的時候才會也有返回的動畫。但是這邊的 transition 會需要修改一下秒數或延遲。

active 這邊是設定飛進來的秒數,因為飛進來跟飛出去的順序不太一樣,飛進來的時候,是 header bottom 先,再來 profile 照片跟 close 按鈕。
飛出去的時候則是剛好相反,所以這邊的延遲秒數會需要調整一下。

設定初始點

我們現在要開始設定這些物件在「還沒飛進來蓋住 gallery 之前的位置」。

記得之前我們有說過,我們有4個動畫物件要設定對吧,這時候我們就一個個去把它們找出來。

.info {
    ...
    .header {transform: translate3d(0,-180px,0);}
    .profile {transform: translate3d(-50%,-300%,0);}
    .close {transform: translate3d(0,-150%,0);}
    .bottom {transform: translate3d(0,220px,0);}
}

這些都設定完之後,畫面上應該就只能看到 gallery 的四張圖了,但現在點擊他們都還不會有反應,這時候我們就要來設定 JS 動畫了。

為動畫制作的 CSS

但是在動畫設定之前,我們先來做個準備工作。

.eachPanel {opacity: 0;}
.show {opacity: 1 !important;}

先把所有的 .eachPanel 都設定成透明的,因為我們要使用 JS 來控制只讓某一個 panl 的透明度變成 1 (可見),如果沒有先把它變成透明的,不管你點什麼,都是 4 個會一起顯示,這樣你永遠都只會看到在最上面的第 4 個,這絕對不是我們要的。

再來就是設定一個等等 for JS 用的 class,這邊我就把它取名叫 .show,這樣等等打開或關閉都可以用它來操作。
那就開始囉~

設定打開動畫

$('.pic').bind('click', function() {
	$('.info').addClass('active');
	const index = $('.pic').index(this) + 1;
 $(`#panel-${index}`).addClass('show')
});
  • $('.pic').bind('click', function() {...}):為每個具有 .pic 類別的元素綁定一個點擊事件。也就是我們 gallery 的每個圖片。
  • $('.info').addClass('active'):當點擊 .pic 時,在 .info 上加上 active 這個 class,這時候就會觸發我們 .active 內的 transform,進而看到移動的動畫。
  • const index = $('.pic').index(this) + 1:取得被點擊的 .pic 元素在所有 .pic 元素中的索引值,並將其加1存入 index。這樣我們就能取得他現在需要打開的是 panel-1panel-4 的哪一個。
  • $(#panel-${index}).addClass('show'):選擇與 index 對應的 #panel- 元素,並加上 show 類別。這時候這個 panel 的透明度會變成可見,也因為同時在父項上加上了 active,所以可以看到移動的動畫。

這時候觸發的 JS 就完成了,接下來我們來做關閉的動畫。

設定關閉動畫

$('.close').bind('click', function() {
    $('.info').removeClass('active');
    setTimeout(function() {
        $('.eachPanel').removeClass('show');
    }, 1000);
});
  • $('.info').removeClass('active'):移除 .info 元素的 active 樣式。
  • setTimeout(function() {...}, 1000):設置一個延遲計時器,1秒後執行內部的函式,這是因為我希望讓畫面上「移除.active的動畫」先跑完,然後再去執行讓 eachPanel 透明度變成100%。
  • $('.eachPanel').removeClass('show'):在延遲1秒後,移除 .eachPanel 元素的 show 樣式,等動畫跑完之後才讓它變透明,不然會看不到飛出去的動畫。

那這樣,這一題就做完了。

https://ithelp.ithome.com.tw/upload/images/20241004/20169403YLgBy18itM.png


Wrap up and go home

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

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


上一篇
Day 24 - CSS Challenge #13:User Gallery(中)
下一篇
Day 26 - CSS Challenge #14:Flip Card(上)
系列文
Dive into CSS Challenge:從問題到解決方案的實踐之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言