今天我們來挑戰Day #3 金字塔,不要問我為什麼多了個e,我們要尊重作者的命名~
金字塔這個作品是一個連貫的動畫,在天空、太陽、金字塔、陰影、地板都用著相同的動畫速度$cubic-bezier: cubic-bezier(.4,0,.49,1);
https://cubic-bezier.com/#.4,0,.49,1
,這動畫效果與ease-in-out
很相似,在動畫速度30%到70%較快速的期間設定了明顯的斷點,使得太陽的移動明顯,讓觀眾們感受到金字塔隨著太陽而有的變化,再來讓我們繼續看下去!
Codepen: https://codepen.io/stevetanus/pen/gOzMgEY
<div class="frame">
<div class="center">
<div class="circle">
<div class="sky"></div>
<div class="sun"></div>
<div class="leftside"></div>
<div class="rightside"></div>
<div class="shadow"></div>
<div class="ground"></div>
</div>
</div>
</div>
.circle
為中心圓,裡面有著天空(.sky)、太陽(.sun)、金字塔(.leftside, .rightside)、陰影(.shadow)、地面(.ground)的元素。
.frame {
background: #272C34;
...
整個frame的背景色偏暗,與中心圓形成對比,讓觀眾更為聚焦在中心圓。
.circle {
position: relative;
overflow: hidden;
width: 180px;
height: 180px;
.sky {
position: absolute;
left: 0;
right: 0;
height: 124px;
...}
.ground {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 56px;
.sky
設定為絕對位置,left:0
、right:0
讓天空的寬度和父層定位點一樣,這邊的高度設定為124px,.ground
的高度設定為58px並加上bottom: 0
置底,相加起來剛好是.circle
的高度。
clip-path
可以讓我們指定元素要呈現的部分,其餘則會被修剪掉(clipped away)。
CSS TRICKS: https://css-tricks.com/almanac/properties/c/clip-path/
在此作品中,有許多三角形和圓形,可以使用clip-path
屬性完成:
.circle {
position: relative;
overflow: hidden;
width: 180px;
height: 180px;
clip-path: circle(90px at 90px 90px);
在.circle
中我們用circle(90px at 90px 90px)
來定義一個圓形半徑為90,圓心為(90,90),其餘則會被clipped掉。
.leftside {
position: absolute;
width: 116px;
height: 57px;
top: 67px;
left: 35px;
clip-path: polygon(0% 100%, 100% 100%, 50% 0%);
.rightside {
position: absolute;
width: 58px;
height: 57px;
top: 67px;
left: 93px;
clip-path: polygon(30% 100%, 100% 100%, 0% 0%);
在.leftside
和.rightside
都用了polygon
去畫出三角形,.leftside
是一個正三角形,先畫兩點(固定y為100%,x從0%到100%),在畫頂點(x為50%,y為0%);.rightside
在.leftside
的上方,要注意到右側的width是左側的一半,其畫出的三角形離左側的正三角形中間加上了30%的右側width,形成一個像是背面的三角形。
.shadow {
position: absolute;
clip-path: polygon(115px 0%, 231px 0%, 80% 100%);
z-index: 2;
top: 124px;
left: -80px;
height: 30px;
width: 360px;
.shadow
也是用polygon
來完成三角形,而因為是金字塔的陰影,我們將width設成360px,在陰影的頂點(80%, 100%)的地方會延伸超過中心圓,讓陰影更為真實。
transform-origin
的屬性很常與transform: rotate()
進行搭配,預設的旋轉中心是center,而我們可以調整旋轉中心來達到日出日落的效果。
https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
.sun {
height: 34px;
width: 34px;
transform-origin: 50% 400%;
animation: sun-goes-down 4s $cubic-bezier infinite;
...}
@keyframes sun-goes-down {
0% {
background: #f57209;
transform: rotate(-70deg);
}
30% {
background: #ffef00;
transform: rotate(-28deg);
}
70% {
transform: scale(1.1);
background: orangered;
}
100% {
background: #f57209;
transform: scale(1) rotate(70deg);
}
}
.sun
我們將其旋轉中心x向右移動50%,向下移動400%,加入sun-goes-down
的動畫後,就會有從-70deg到-28deg到0deg(中間)到70deg,離開畫面的效果。
.shadow {
transform-origin: 50% 0%;
animation: shadow-on-the-floor 4s $cubic-bezier infinite;
@keyframes shadow-on-the-floor {
0% {
transform: scaleY(0);
clip-path: polygon(115px 0%, 231px 0%, 100% 100%);
}
30% {
transform: scaleY(1);
clip-path: polygon(115px 0%, 231px 0%, 80% 100%);
}
55% {
transform: scaleY(0.4);
}
75% {
transform: scaleY(1);
}
100% {
transform: scaleY(0);
clip-path: polygon(115px 0%, 231px 0%, 0% 100%);
}
}
.shadow
是作者提到不簡單的一塊,我們將旋轉中心設為(50%, 0%),如此陰影就會固定在金字塔底部旋轉,動畫效果在0%時X軸拉得更長,30%收回原本的陰影,55%縮小到0.4倍,75%回到1倍,最後縮小到一倍(陰影本身寬度為360px,必須注意在30%到100%間,clip-path的頂點會逐漸往左側到X軸0%的位置。)
.rightside {
animation: pyramide-shading 4s $cubic-bezier infinite reverse;
.rightside
的animation-direction
設定為reverse,是相對於.leftside
的動畫的反向設定。
CSS
目標 | 屬性 |
---|---|
思考斷點、動畫速度 | cubic-bezier、ease-in-out... |
畫出圖形 | clip-path |
常見動畫 | transform-origin + rotate |
今天的挑戰老實說挺難的,在做第二次的時候,還是很多不上手的地方,自己是在背景顏色做了些變化。沒想到這麼快中秋連假就結束了,我的文章儲備數還是0...緊接而來的是上班跟颱風,祝福大家不受到颱風影響,明天都收拾好心情開始上班~