iT邦幫忙

2022 iThome 鐵人賽

DAY 4
0
自我挑戰組

Do you wanna play? CSS game ぎりぎり系列 第 4

[Day 4] The Pyramide: 金字塔日落陰影動畫

  • 分享至 

  • xImage
  •  

The Pyramide


今天我們來挑戰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


1. HTML

<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)的元素。


2. CSS

.frame

.frame {
  background: #272C34;
  ...

整個frame的背景色偏暗,與中心圓形成對比,讓觀眾更為聚焦在中心圓。

.sky

.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:0right:0讓天空的寬度和父層定位點一樣,這邊的高度設定為124px,.ground的高度設定為58px並加上bottom: 0置底,相加起來剛好是.circle的高度。

clip-path屬性

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,形成一個像是背面的三角形。
https://ithelp.ithome.com.tw/upload/images/20220911/20152191Q6GluWyQIQ.jpg

  .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%)的地方會延伸超過中心圓,讓陰影更為真實。
https://ithelp.ithome.com.tw/upload/images/20220911/20152191DJbW8MfSMo.jpg

動畫 (transform-origin的應用)

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;

.rightsideanimation-direction設定為reverse,是相對於.leftside的動畫的反向設定。


打包帶走(take away)

CSS

目標 屬性
思考斷點、動畫速度 cubic-bezier、ease-in-out...
畫出圖形 clip-path
常見動畫 transform-origin + rotate

後記

今天的挑戰老實說挺難的,在做第二次的時候,還是很多不上手的地方,自己是在背景顏色做了些變化。沒想到這麼快中秋連假就結束了,我的文章儲備數還是0...緊接而來的是上班跟颱風,祝福大家不受到颱風影響,明天都收拾好心情開始上班~


上一篇
[Day 3] Menu Icon: 漢堡包 好好ㄘ
下一篇
[Day 5] Loadinggg: 這30天Loading好重(?
系列文
Do you wanna play? CSS game ぎりぎり30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言