iT邦幫忙

2022 iThome 鐵人賽

DAY 22
1
自我挑戰組

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

[Day 22] Send Mail: 您的一封來信

  • 分享至 

  • xImage
  •  

在製作個人網頁時,通常會有一個contactme(與我聯絡)的表格,這時候,我們就可以想想看怎麼美化我們的送信動畫~
今天我們來實作Day #20

Send Mail

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


1. HTML

<div class="frame">
  <input type="checkbox" id="cb">
  <label for="cb" class="button">Send mail</label>
  <label for="cb" class="button reset">Reset</label>
  <div class="circle"></div>
  <div class="circle-outer"></div>
  <svg class="icon mail">
<!-- 信封四方形 -->
    <polyline points="119,1 119,69 1,69 1,1"></polyline>
<!-- 開關三角形 -->
    <polyline points="119,1 60,45 1,1 119,1"></polyline>
  </svg>
  <svg class="icon plane">
<!-- 飛翼三角形 -->
    <polyline points="119,1 1,59 106,80 119,1"></polyline>
<!-- 飛機中間線和基座 -->
    <polyline points="119,1 40,67 43,105 69,73"></polyline>
  </svg>
</div>

input:checkbox放在最前面,有兩個label指向這個checkbox,中間有.circle圓形背景和.circle-outer圓形邊框線,兩個svg.mail.plane,分別為信封和飛機,飛機的SVG較難理解,我下面透過註解與截圖呈現:
飛翼三角形
https://ithelp.ithome.com.tw/upload/images/20220929/20152191SAgYkwZWb9.jpg
飛機中間線和基座
https://ithelp.ithome.com.tw/upload/images/20220929/20152191Lzsxw4Di0M.jpg


SCSS(CSS)

#cb

#cb {
  display: none; //讓checkbox消失,用label去做切換
}

.circle, .circle-outer

.circle {
  position: absolute;
  width: 200px;
  height: 200px;
  top: 65px;
  left: 100px;
  background: #354A5F;
  border-radius: 50%;
}

.circle-outer {
  @extend .circle;
  box-sizing: border-box;
  background: none;
  border: 4px solid #354A5F;
}

.circle-outer.circle外圍的框線,兩者在後面的動畫會有差異。

.icon, .plane, .mail

.icon {
  position: absolute;
  z-index: 2;
  top: 130px;
  left: 140px;
  fill: none;  // 去除預設的黑色
  stroke-width: 2px;
  stroke: #ecf0f1;
  stroke-linecap: square;  // 方角,且會比butt再延長些路徑的長度。
  stroke-dasharray: 325;
  
  &.mail {
    width: 120px;
    height: 70px;
    stroke-dashoffset: 0;
  }
  
  &.plane {
    width: 120px;
    height: 110px;
    stroke-dashoffset: 325;
  }
}

stroke-dashyarray: 325使得.mail充滿實線,而.planestroke-dashoffset: 325將實線推移了325單元,讓飛機一開始是空白透明的。關於要如何取得SVG線段長度,可以參考這篇文章的末段svg-line-animation-works,使用getTotalLength(),但其方法對於SVG內有兩個以上重疊線段不管用,這時候可能就要用推估的,從錯中修正。

CSS stroke-linecap: https://css-tricks.com/almanac/properties/s/stroke-linecap/

.button

.button {
  ...
  z-index: 10;
  ...
  border-radius: 20px;
  font-weight: 600;
  text-transform: uppercase;
  font-size: 15px;
  cursor: pointer;
  
  &.reset {
    opacity: 0;
    z-index: 5;
  }
  
  &:hover {
    background: #1abc9c;
    color: #fff;
  }
}

.reset重設按鈕的z-index為5,小於前面的按鈕(10),並設定為透明的。

checkbox:checked(當按鈕被按下時)

按鈕們

#cb:checked ~ .button {
  animation: button 1.5s ease-in-out 1.7s; // 延遲1.7s出發,飛機駛離動畫為2.4s結束
  animation-fill-mode: both;
}

#cb:checked ~ .reset {
  animation: reset 1s ease-in-out 3.7s;
  animation-fill-mode: both;
}

@keyframes button {
	0% {
		transform: scale(1);
	}
	30% {
		background: #1abc9c; // 變為深綠色背景
		color: transparent; // 文字透明
		width: 200px;
		left: 100px;
	}
	50%,60% {
    // 縮小成圓球,原本height為40px
		width: 40px;
		left: 180px;
		transform: scale(1); 
	}
	70% {
		transform: scale(1.1); // 放大離開
	}
	100% {
		width: 40px;
		left: 180px;
		background: #1abc9c;
		color: transparent;
		transform: scale(0);
	}
}

@keyframes reset {
  // 由暗轉明
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

圓圈背景

#cb:checked ~ .circle {
  animation: circle 1s ease-in-out;
  animation-fill-mode: both;
}

#cb:checked ~ .circle-outer {
  animation: circle .8s ease-in-out .2s;
  animation-fill-mode: both;
}

@keyframes circle {
	0% {
		transform:  scale(1);
	}
	20% {
		transform: scale(1.1);
	}
	100% {
		transform: scale(0);
	}
}

.circle-outer的動畫晚.2s出發,產生較晚但同時收縮完畢的感覺(1s)。

SVG信封、紙飛機

#cb:checked ~ .mail {
  stroke-dashoffset: 326; // 所有白線被推移消失
  transition: stroke-dashoffset 1s ease-in-out;
}

#cb:checked ~ .plane {
  stroke-dashoffset: 0;  // 所有白線出現
  transition: stroke-dashoffset 1s ease-in-out .6s; // 0.6s動畫開始,剛好是接著信封的動畫,產生連貫的效果。
  animation: fly 2.4s ease-in-out;
  animation-fill-mode: both;
}

@keyframes fly {
	0%, 50% {
    scale: 1;
	}
	60% {
    scale: 1.05;
    translate: -20px 10px; //向左下稍微移動飛出
	}
	70% {
		opacity: 1;
	}
	85% {
		opacity: 0;
	}
	100% {
    translate: 300px -150px; //往右上飛出消失
    scale: 0.4;
		opacity: 0;
	}
}

打包帶走(take away)

HTML

目標 屬性
寄信元素: 信封、紙飛機 參考上面程式碼.mail,.plane
CSS
目標 屬性
------------- -------------
方角邊框 stroke-linecap: square ,且會比butt再延長些路徑的長度。
文字透明 color: transparent
取得SVG的path長度 path.getTotalLength(),但重疊的線段不適用

後記

今天早上很早就起床了,所以有先寫一些,還是沒能在早上就發文~儲備文章是真D難...


上一篇
[Day 21] Slider with Radio Button: 三點換頁
下一篇
[Day 23] Pac-Man: パックマン小精靈
系列文
Do you wanna play? CSS game ぎりぎり30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Felix
iT邦研究生 2 級 ‧ 2022-09-30 02:27:33

加油,這個 SVG 應用太厲害啦!

謝謝你~~~

我要留言

立即登入留言