效果預覽
按下右側的“點選預覽”按鈕可以在當前頁面預覽,點選連結可以全屏預覽。
https://codepen.io/comehope/pen/pxLbjv
可互動視訊
此視訊是可以互動的,你可以隨時暫停視訊,編輯視訊中的程式碼。
請用 chrome, safari, edge 開啟觀看。
https://scrimba.com/p/pEgDAM/cMV8euJ
原始碼下載
每日前端實戰系列的全部原始碼請從 github 下載:
https://github.com/comehope/front-end-daily-challenges
程式碼解讀
定義 dom,容器 .umbralla
中包含 2 個元素,.canopy
代表傘蓋,.shaft
傘柄:
<figure class="umbralla">
<div class="canopy"></div>
<div class="shaft"></div>
</figure>
居中顯示:
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(skyblue, lightblue);
}
設定偽元素的共有屬性:
.umbrella *::before,
.umbrella *::after {
content: '';
position: absolute;
}
先畫出雨傘開啟的樣子。
設定容器尺寸,其中 font-size
的屬性值後面還要用到,所以定義了一個變數:
:root {
--font-size: 10px;
}
.umbrella {
position: relative;
width: 25em;
height: 26em;
font-size: var(--font-size);
}
定義傘蓋的尺寸:
.umbrella .canopy {
position: absolute;
width: inherit;
height: 5.5em;
top: 2.5em;
}
用 ::before
偽元素畫出傘蓋的上半部分,方法先畫一個半圓,然後在垂直方向上壓縮它:
.umbrella .canopy::before {
width: inherit;
height: 12.5em;
background: rgb(100, 100, 100);
border-radius: 12.5em 12.5em 0 0;
transform: scaleY(0.4);
top: -4em;
}
用 ::after
偽元素畫出傘蓋的下半部分:
.umbrella .canopy::after {
width: inherit;
height: 1.5em;
background-color: #333;
top: 4em;
border-radius: 50%;
}
畫出傘柄的長杆:
.umbrella .shaft {
position: absolute;
width: 0.8em;
height: 18em;
background-color: rgba(100, 100, 100, 0.7);
top: 5.5em;
left: calc((100% - 0.8em) / 2);
}
用偽元素畫出傘杆頂部露出傘蓋的尖頭,方法和畫傘蓋上半部分類似,先畫出半圓,然後在水平方向上壓縮它:
.umbrella .shaft::before {
width: 6em;
height: 3em;
background-color: rgba(100, 100, 100, 0.7);
left: calc((100% - 6em) / 2);
top: -5.5em;
border-radius: 6em 6em 0 0;
transform: scaleX(0.1);
}
畫出雨傘的鉤形把手:
.umbrella .shaft::after {
box-sizing: border-box;
width: 4em;
height: 2.5em;
border: 1em solid #333;
top: 100%;
left: calc(50% - 4em + 1em / 2);
border-radius: 0 0 2.5em 2.5em;
border-top: none;
}
至此,完成了雨傘開啟的樣子,接下來通過變形畫出雨傘合上時的樣子。
先把傘蓋的合上,方法是在水平方向上壓縮,在垂直方向上拉伸:
.umbrella .canopy {
transform-origin: top;
transform: scale(0.08, 4);
}
隱藏傘蓋的下半部分:
.umbrella .canopy::after {
transform: scaleY(0);
}
讓傘傾斜,因為豎著的傘有點呆板,所以增加一點變化:
.umbrella {
transform: rotate(-30deg);
}
至此,雨傘合上時的樣子也完成了,接下來要把它變為 toggle 控制元件了。
在 dom 中增加一個 checkbox
控制元件:
<input type="checkbox" class="toggle">
<figure class="umbrella">
<!-- 略 -->
</figure>
設定控制元件與雨傘一樣大,並置於雨傘圖層的上層:
.toggle {
position: absolute;
filter: opacity(0);
width: 25em;
height: 26em;
font-size: var(--font-size);
cursor: pointer;
z-index: 2;
}
checkbox
控制元件的未選中狀態對應雨傘合上時的樣子,也就是目前雨傘的樣子,所以只要指定控制元件被選中狀態對應的雨傘開啟時的樣子就可以了。因為合上雨傘是對幾個元素進行變形得到的,所以轉換到雨傘開啟狀態就是取消變形。
先讓傘正過來:
.toggle:checked ~ .umbrella {
transform: rotate(0deg);
}
然後把傘蓋開啟:
.toggle:checked ~ .umbrella .canopy {
transform: scale(1, 1);
}
再顯示出傘蓋的下半部分:
.toggle:checked ~ .umbrella .canopy::after {
transform: scaleY(1);
}
最後,設定以上幾個元素的緩動效果:
.umbrella,
.umbrella .canopy,
.umbrella .canopy::after {
transition: 0.3s cubic-bezier(0.5, -0.25, 0.5, 1.25);
}
大功告成!