iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
自我挑戰組

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

[Day 25] Animated Typography: 偷走你3秒的動態字卡

  • 分享至 

  • xImage
  •  

比起一般的標題,有時候加上些動畫的標題更為吸引人,特別是今天的動態字卡,絕對會吸住你的眼睛!?
今天我們來實作Day #23

Animated Typography


CodePen: https://codepen.io/stevetanus/pen/XWqEeJq


1. HTML

<div class="frame">
  <div class="circle"></div>
  <div class="line left"></div>
  <div class="line right"></div>
  <div class="bracket left"></div>
  <div class="bracket right"></div>
  <div class="small top">more</div>
  <div class="big">practices</div>
  <div class="small bottom">less excuses</div>
  <div class="hide top"></div>
  <div class="hide bottom"></div>
</div>

circleline為一開始的動畫元素,後面會消失。
.hide是上下的檔板,擋住文字和引號,有揭開的動畫。
.bracket為兩邊的引號,.small.big為小文字和大文字。


2. SCSS(CSS)

.circle(動畫1秒)

.circle {
  ...
  animation: circle 1s ease-in-out;
  animation-fill-mode: forwards; // 維持動畫結束時的狀態
}
// 放大1.2倍快速縮小消失
@keyframes circle {
	0% {
    scale: 1;
	}
	50% {
    scale: 1.2;
	}
	90%, 100% {
    scale: 0;
	}
}

.line.left, .line.right(延遲0.8秒,動畫1秒)

.line {
  position: absolute;
  z-index: 10;
  width: 150px;
  height: 4px;
  top: 198px;
  background: #fff;
  scale: 0 1;
  
  &.left {
    left: 50px; // 左推50px
    transform-origin: 100% 50%;
    animation: lines 1s ease-in-out .8s, line-left 1s steps(1) .8s;
  }
  right: 50px; // 右推50px
    transform-origin: 0% 50%;
    animation: lines 1s ease-in-out .8s, line-right 1s steps(1) .8s;
  }
}

transform-origin使得.left從右側開始動畫,.right從左側開始動畫。
line-left的動畫中,animation-timing-function設定為step(逐格動畫),steps(1)steps(1, end)是相同的(第1個參數是動畫的間隔數,第2個參數預設end),表示動畫在開始到結束間有一格動畫,並停在結束動畫的前一格,在這邊的話,會有0%跟50%的動畫效果。

MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function
CSS動畫好文: https://ithelp.ithome.com.tw/articles/10200709

我們再來看線段的動畫:

// 
@keyframes lines {
	0% {
		scale: 0 1;
	}
	50% {
		scale: 1 1;
	}
	100% {
		scale: 0 1;
	}
}
// 中心從右邊跳到左邊
@keyframes line-left {
	0% {
		transform-origin: 100% 50%;
	}
	50% {
		transform-origin: 0% 50%;
	}
}
// 中心從左邊跳到右邊
@keyframes line-right {
	0% {
		transform-origin: 0% 50%;
	}
	50%{
		transform-origin: 100% 50%;
	}
}

配合steps(1),在動畫50%時轉換中心改變達到漂亮的線段伸縮效果。

.bracket(延遲1.7秒,動畫0.4秒)

.bracket {
  position: absolute;
  z-index: 10;
  height: 70px;
  width: 4px;
  top: 165px;
  background: #fff;
  animation: bracket .4s ease-out 1.7s;
  animation-fill-mode: both;
  
  &:before, &:after {
    position: absolute;
    display: block;
    content: '';
    width: 25px;
    height: 4px;
    background: #fff;
  }

.bracket為白色直長條,:before:after為頂端的橫短條

.left(延遲2.1秒,動畫0.2秒)

&.left {
    left: 50px;
    &:before {
      top: 0;
      left: 0;
      transform-origin: 0% 50%;
      animation: bracket-line .2s ease-out 2.1s;
      animation-fill-mode: both;
    }
    
    &:after {
      bottom: 0;
      left: 0;
      transform-origin: 0% 50%;
      animation: bracket-line .2s ease-out 2.1s;
      animation-fill-mode: both;
    }
  }

.right(延遲2.1秒,動畫0.2秒)

 &.right {
    right: 50px;
    &:before {
      top: 0;
      right: 0;
      transform-origin: 100% 50%;
      animation: bracket-line .2s ease-out 2.1s;
      animation-fill-mode: both;
    }
    
    &:after {
      right: 0;
      bottom: 0;
      transform-origin: 100% 50%;
      animation: bracket-line .2s ease-out 2.1s;
      animation-fill-mode: both;
    }
  }

可以看到.left.right透過絕對定位來形成兩邊的引號

// 從中心長出y的長度
@keyframes bracket {
  0% {
    scale: 1 0;
  }
  100% {
    scale : 1 1;
  }
}
// 從給定的中心長出x的長度
@keyframes bracket-line {
  0% {
    scale: 0 1;
  }
  100% {
    scale: 1 1;
  }
}

.hide.top, .hide.bottom(延遲1.7秒,動畫0.4秒)

.hide {
  position: absolute;
  z-index: 7;
  width: 400px;
  height: 40px;
  background: #E16D6c;
  left: 0;
  animation: reveal .4s ease-out 1.7s;
  animation-fill-mode: both;
  
  &.top {
    bottom: 49%;
    transform-origin: 50% 0%;
  }
  
  &.bottom {
    top: 49%;
    transform-origin: 50% 100%;
  }
}

為擋住中間80px(400*2%)的檔板,transform-origin分別為頂部與底部,再加上動畫reveal形成打開檔板的效果。

@keyframes reveal {
	0% {
		scale: 1 1
	}
	100% {
		scale: 1 0
	}
}

.small(延遲2.2秒,動畫.5s)

小文字的動畫排在最後,透過translate來達到移動的效果。

@keyframes small-top {
	0% {
		translate: -20px; // small-bottom 則為20px
		opacity: 0;
	}
	100% {
		translate: 0px;
		opacity: 1;
	}
}

打包帶走(take away)

CSS

目標 屬性
逐格動畫 animation-timing-function: steps(n, <jumpterm>), step-start, step-end
引號 .bracket加上偽元素:before:after,透過絕對位置調整
改變動畫位置,達到伸縮線跟檔板的應用 transform-origin的變化

後記

動態字卡的動畫效果十分滑順,一個接著一個,有著好的延遲與動畫時間搭配,而在學習到step逐格動畫之後,也會使得動畫變得更加多元,感謝您的收看~快去把握剩下的周末時光吧!


上一篇
[Day 24] Fitness Tracker: 您今天運動了嗎~我沒有...
下一篇
[Day 26] Button: 咔鏗完成!
系列文
Do you wanna play? CSS game ぎりぎり30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言