Please enable Javascript to view the contents

【JS30系列】Day 05:Flex Panels Gallery

 ·  ☕ 2 分鐘 · 👀... 閱讀
Flex Panels Gallery
Javascript 30 Day05: Flex Panels Gallery

Wes Bos 的原始專案:JS30 Day05

專案目標:

運用 flex 以及綁定 click 和 transitionend 監聽事件來呈現畫廊效果。
點擊後相應的圖片與字體會放大,再次點擊則回復原狀。


實作成果

步驟一:CSS 添加 flex 等等屬性

在正式寫 js 之前,首先先對 CSS 做一些修改。

由於一開始的專案畫面,五張圖片是平行呈現,為了呈現最終畫面的效果,首先在 .panels 增加 flex 屬性。

1
2
3
4
.panels {
  /* 以下為新增屬性 */
  display: flex;
}

接下來針對 .panels 類別底下的 .panel類別。因為要平均分配每張圖片的呈現空間,所以添加 flex: 1;

.panel 類別底下的三個 <p> 段落需要由上而下平行呈現,所以添加了 flex-direction: column;

.panel > * 類別也做出相應調整。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
.panel {
  /* 以下為新增屬性 */
  flex: 1;
  display: flex;
  flex-direction: column;
}

.panel > * {
  /* 以下為新增屬性 */
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

以上這些基本修改完成後,接下來是針對畫面點擊效果。
設計在 .panel 上添加 .open,並於完成 transition 動畫特效後,再添加 .open-end 的第二次特效。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.panel.open {
  font-size: 40px;
  /* 以下為新增屬性 */
  flex: 5;
}

/* 以下為新增屬性 */
.panel > *:first-child{transform: translateY(-100%);}
.panel.open-end > *:first-child{transform: translateY(-0%);}
.panel > *:last-child{transform: translateY(100%);}
.panel.open-end > *:last-child{transform: translateY(-0%);}

圖片被點擊後,圖片所占空間會變大,字體也會變大,所以 .panel.open 中更改了 font-size 字體大小,且將 flex 設為 5

由於初始專案在 .panel 中有設定 transition,所以會針對字體大小和圖片空間產生動畫特效。

1
2
3
4
transition:
  font-size 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11),
  flex 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11),
  background 0.2s;


步驟二:為 panel 綁定事件監聽

CSS 的部分都修改好後,就正式進入 js 的部分。

主要就是用 querySelectorAll 撈出所有 .panel 的 DOM 元素,並在上面綁定兩個事件監聽。

第一個是 addEventListener('click', openPanel)。在點擊的時候為 .panel 添加上 .open 類別,做出圖片空間變大以及字體變大的特效。

第二個是 addEventListener('transitionend', openEnd)。這個事件監聽是在完成 .open 特效後才發生,因此使用 transitionend 事件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const panels = document.querySelectorAll(".panel");

function openPanel(){
  this.classList.toggle('open');
}

function openEnd(e){
  // this.classList.toggle('open-end');
  if (e.propertyName.includes('font-size')) {
    this.classList.toggle('open-end');
  }
}

panels.forEach(el => el.addEventListener('click', openPanel));
panels.forEach(el => el.addEventListener('transitionend', openEnd));

比較特別的是,因為 .open 觸發了兩次的 transition 第一次是 font-size: 40px;,第二次是 flex: 5;,所以我們所添加的 transitionend 事件監聽也會觸發兩次,故 toggle('open-end') 發生兩次後,變成 .open-end 類別沒有被成功添加上去。

所以這裡必須再加入一個判斷式,判斷所點擊的對象是否有內含屬性 font-size: 40px;flex: 5;

Wes Bos 的判斷式是寫 e.propertyName.includes('flex'),這裡寫 e.propertyName.includes('font-size') 也是一樣的。


延伸閱讀:



分享

Sylvia-H
作者
Sylvia-H
Web Developer / F2E 前端筆記

comments powered by Disqus