iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 26
0

Day26-課題內容

在今天的課題當中,我們要將第22天的課題 Follow Along Link HighLighter 聚光燈的效果,做進一步的利用。
當我們把滑鼠移到列表標題上時,下方的列表就會浮現,並且將我們的聚光燈移到列表上。[1]
實作連結

進入課題

根據第22天的課題內容,我們已經學會聚光燈元素的原理及方法。而要讓內容呈現的話,就需要來認識 display:none 以及 opacity 這兩個 CSS 屬性。

Display:none

display:none CSS 屬性,能將元素從畫面中移除,讓頁面呈現時看不出有該元素的存在。另一種使元素消失的方法為 visibility:hidden,使用這種 CSS 屬性,雖然也能讓元素從畫面上消失,但是他會保留原本元素的位置與大小,所以在頁面中會看到一塊空白。[2]

Opacity

opacity CSS 屬性,代表的是元素的透明度,其值為0~1。0代表透明程度為0%,因此元素為完全不透明狀態。1則是代表100%,因此元素為完全透明。[3]

了解以上兩個 CSS 屬性的特性之後,我們就可以理解為何需要額外加上 display:none 屬性,如果我們只更動了 opacity:0 這個屬性,則會發生看不到東西卻點得到的靈異事件:

撰寫程式碼

將以上兩種屬性結合起來,並透過觸發事件來更動元素 CSS 屬性,我們就能完成今天的課題。
首先我們將需要的元素選取起來,並加上監聽事件 onmouseenter<mouseleave> ,讓滑鼠移入與移出指定元素的時候觸發事件:

const triggers = document.querySelectorAll('.cool > li');
const background = document.querySelector('.dropdownBackground');
const nav = document.querySelector('.top');

triggers.forEach(trigger => trigger.addEventListener('mouseenter', handleEnter));
triggers.forEach(trigger => trigger.addEventListener('mouseleave', handleLeave));

這邊加上監聽事件的元素選為 <li> 容器元素,這是因為如果我們選擇裡頭的子元素為事件目標,當我們滑鼠移到子元素之間的空隙,我們的表單就因為無觸發 onmouseenter 事件而消失。

在我們的觸發函式之中,我們要完成 CSS 屬性的更換,因此可以透過將元素新增、移除 class 來做出此效果,我們希望元素先出現在頁面上,延遲之後再顯示內容,因此我們分別加上兩個 class ,第一個先將 display:none 屬性更改掉,後面的則是利用 setTimeout() 方法,延遲一段時間後更改內容的透明度,而當滑鼠移開時,則是同時移除:

function handleEnter(event) {
    const showItem = event.target;
    showItem.classList.add('trigger-enter');
    setTimeout(function () {
        if (showItem.classList.contains('trigger-enter')) {
            showItem.classList.add('trigger-enter-active');
        }
    }, 150);
};

function handleLeave(event) {
    const missItem = event.target;
    missItem.classList.remove('trigger-enter', 'trigger-enter-active');
};
.trigger-enter .dropdown {
    display: block;
}

.trigger-enter-active .dropdown {
    opacity: 1;
}

再來要加上聚光燈的效果,我們一樣也是透過 element.getBoundingClientRect() 方法,取得元素的大小以及位置。但是我們要特別注意到這次作為聚光燈背景的元素 <div class="dropdownBackground"> 是被放在 <nav> 容器元素之下,且 position:absolute 屬性,是相對其父元素做定位,因此當容器上方有其他高度存在的元素,將造成聚光燈打歪,因此我們需要額外加上<nav> 容器的位置幫助判斷,完整函式內容程式碼如下:

function handleEnter(event) {
    const showItem = event.target;
    showItem.classList.add('trigger-enter');
    setTimeout(function () {
        if (showItem.classList.contains('trigger-enter')) {
          showItem.classList.add('trigger-enter-active');
        }
      }, 150);
    background.classList.add('open');
    
    //取得觸發事件父元素中的 '.dropdown' 子元素
    const dropdown = this.querySelector('.dropdown');
    //取得該子元素的大小及位置資料
    const dropdownCoords = dropdown.getBoundingClientRect();
    //取得 <nav> 元素的大小及位置資料
    const navCoords = nav.getBoundingClientRect();
    //設定聚光燈背景元素的大小及位置 
    background.style.width = `${dropdownCoords.width}px`;
    background.style.height =  `${dropdownCoords.height}px`;
    background.style.top = `${dropdownCoords.top - navCoords.top}px`  ;
    background.style.left = `${dropdownCoords.left- navCoords.left}px`;
};
function handleLeave(event) {
      const missItem = event.target;
      missItem.classList.remove('trigger-enter', 'trigger-enter-active');
      background.classList.remove('open');
};
.dropdownBackground.open {
    opacity: 1;
}

總結

今天學到新的 CSS 屬性如下:

  1. display:none
  2. visibility:hidden
  3. opacity

今天我們將第22天學到的方法,結合新的 CSS 屬性,做出隱形的表單。其實我們可以發現,要做出頁面特效的話,透過簡單的監聽事件函式與元素 CSS 屬性更換,就可以創造出許多酷炫的頁面特效。
到目前為止,JS30已經進入倒數5天,相信大家都跟我一樣對網頁特效的恐懼感有逐漸消失,深信在完成JS30之後,我們都能具備將腦中的特效想法,實作出來的能力!

參考資料

  1. javascript30
  2. CSS Layout - The display Property
  3. opacity

上一篇
JS25-Event Capture, Propagation, Bubling & Once
下一篇
JS30-Day27-Click & Drag
系列文
新手也能懂的JS3028

尚未有邦友留言

立即登入留言