題目除了基本 Gallery 介面樣式以外,還有點擊後的介面
上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
這個題目要求我們製作一個 User Gallery
我們昨天已經把最開始的四格 User Gallery 跟滑鼠指上的效果都做出來了,也把點開的 info 頁面作了一半(如下圖),今天我們就來把最後的照片、右上角關閉按鈕、JS控制開關的部分、動畫都一次做完看看。
$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
定位在父容器的中心位置。width
和 height
使用變數 $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 秒開始變化。.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",這樣就好囉。
因為需要使用 JS 來寫 click 事件,所以我這邊還是引用了 css challenge 官方的 JS 來做使用,當然你也可以用你自己喜歡的。
.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 動畫了。
但是在動畫設定之前,我們先來做個準備工作。
.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-1
到 panel-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 樣式,等動畫跑完之後才讓它變透明,不然會看不到飛出去的動畫。那這樣,這一題就做完了。
希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。
那今天就先到這裡,明天我們再繼續來玩下一集。