iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0

16 - Mouse Move Shadow

tags: JavaScript30

專案簡介

第十六天的主要目標是學習建構滑鼠的移動事件,並釐清 this 和 e.target 的差異

課程影片:JS30 16
導讀影片:Alex

初始文件

Github 檔案位置:16 - Mouse Move Shadow

網頁一開始的樣子如下,我們的目標是隨著滑鼠移動而創造多個文字陰影特效

可以先去看看 最後的成品

正式製作

製作文字陰影特效

首先加上監聽,並利用 object 的解構賦值創建等等會用到的變數

const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');

function shadow(e) {
  const { offsetWidth: width, offsetHeight: height } = hero;
  // 這樣的作法會等於 const width = hero.offsetWidth
  // console.log(hero.offsetWidth);
  // console.log(width)

  let { offsetX: x, offsetY: y } = e;
  // 同理 let x = e.offsetX
}

hero.addEventListener('mousemove', shadow);

接下來是觀念釐清
在 eventHandler 裡的 this 指的是被監聽的 DOM 元素 hero,因此無論什麼情況 this 都會是 hero

但 e.target 就不一樣了,他會抓到監聽範圍內觸發事件的元素,這裡就會抓到 h1

這裡會導致 offsetX: x, offsetY: y 抓到的座標是在 h1 元素的左上角,而不是 hero 的左上角,因此需要加回 e.target.offsetLeft 這個值是 hero 與 h1 的座標差值

function shadow(e) {
    // ...
    if (this !== e.target) { // 當碰到 h1 元素時
      x = x + e.target.offsetLeft; // 加回缺少的 left 值
      y = y + e.target.offsetTop; // 加回缺少的 top 值
    }
}


最後這裡,walk 代表的是我們想讓陰影特效活動的範圍大小,以下公式的邏輯如下

  1. 數標位置 / 總寬高 取出百分比
  2. 百分比 * walk 取得數值
  3. 以取得的數值 - (walk / 2) 讓特效置中

最後再以算出來的數值渲染上陰影特效就完成了

 const walk = 500; // 500px

function shadow(e) {
    // ...
    const xWalk = Math.round((x / width * walk) - (walk / 2)); // 
    const yWalk = Math.round((y / height * walk) - (walk / 2));
    
    text.style.textShadow = `
      ${xWalk}px ${yWalk}px 0 rgba(255,0,255,0.7), 
      ${xWalk * -1}px ${yWalk}px 0 rgba(0,255,255,0.7),
      ${yWalk}px ${xWalk * -1}px 0 rgba(0,255,0,0.7),
      ${yWalk * -1}px ${xWalk}px 0 rgba(0,0,255,0.7)
    `;
}

最後程式碼

const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');
const walk = 500; // 500px

function shadow(e) {
  const { offsetWidth: width, offsetHeight: height } = hero;
  // 這樣的作法會等於 const width = hero.offsetWidth
  // console.log(hero.offsetWidth);
  // console.log(width)

  let { offsetX: x, offsetY: y } = e;
  // 同理 let x = e.offsetX
  
  if (this !== e.target) { // 當碰到 h1 元素時
    x = x + e.target.offsetLeft; // 加回缺少的 left 值
    y = y + e.target.offsetTop; // 加回缺少的 top 值
  }
  // console.log(this);
  // console.log(e.target);


  const xWalk = Math.round((x / width * walk) - (walk / 2)); // 
  const yWalk = Math.round((y / height * walk) - (walk / 2));
  
  // 製作陰影
  text.style.textShadow = `
    ${xWalk}px ${yWalk}px 0 rgba(255,0,255,0.7), 
    ${xWalk * -1}px ${yWalk}px 0 rgba(0,255,255,0.7),
    ${yWalk}px ${xWalk * -1}px 0 rgba(0,255,0,0.7),
    ${yWalk * -1}px ${xWalk}px 0 rgba(0,0,255,0.7)
  `;
}

hero.addEventListener('mousemove', shadow);

完成結果圖

最後的成品

結語

以上是第十六天的製作紀錄,如有錯誤或不足的地方還請多多指教 >.<

CSS Text Shadow on Mouse Move Effect - #JavaScript30 16/30
[ Alex 宅幹嘛 ] 深入淺出 Javascript30 快速導覽 | Day 16:Mouse Move Shadow
MDN Web Docs


上一篇
JS30 -> 15 - LocalStorage
下一篇
JS30 -> 17 - Sort Without Articles
系列文
剛接觸前端一個月的小白 - JavaScript30 挑戰筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言