前言
JS 30 是由加拿大的全端工程師 Wes Bos 免費提供的 JavaScript 簡單應用課程,課程主打 No Frameworks、No Compilers、No Libraries、No Boilerplate 在30天的30部教學影片裡,建立30個JavaScript的有趣小東西。
另外,Wes Bos 也很無私地在 Github 上公開了所有 JS 30 課程的程式碼,有興趣的話可以去 fork 或下載。
本日目標
讓文字陰影跟著滑鼠一起移動。

解析程式碼
HTML 部分
在.hero內放入我們預計要用來產生文字陰影(Text Shadow)效果的文字(h1)。
h1上有一個特殊的屬性:contenteditable,表示<h1></h1>之間的內容是可以被修改的。
| 1 | <div class="hero"> | 
<h1></h1>之間的內容可被修改如下:
- 
修改前 
  
- 
修改後 
  
JS 部分
在實作文字陰影效果之前,我們要先取得.hero和內部的h1。
| 1 | const hero = document.querySelector('.hero'); | 
由於我們的目的是產生文字陰影隨著滑鼠移動的效果,所以在.hero上註冊mousemove 事件的監聽器並以shadow()進行事件處理。
| 1 | hero.addEventListener('mousemove',shadow); | 
shadow() :
const { offsetWidth: width, offsetHeight: height} = hero; : 最初,我們必須先取得.hero的width、height,用來計算後續文字陰影的移動量。
let { offsetX: x, offsetY: y} = e; : 我們也必須知道現在滑鼠所在的座標。
注意,這裡我們使用的是 ES6 Destructuring Assignment(解構賦值)的語法所以不使用像是const width = hero.offsetWidth;、const height = hero.offsetHeight;這種較繁瑣的寫法。
| 1 | function shadow(e){ | 
因為event.offsetX、event.offsetY取得的是滑鼠相對於事件源元素(srcElement)的X,Y坐標,所以當我們把滑鼠移動到h1得到的座標就會是以h1的左上角為(0,0)開始的位置。
這樣的位置是有問題的,我們原本要取得的應該是滑鼠在視窗裡面的位置(或說是滑鼠相對.hero的位置),所以必須要做一點修正。
我們在觸發mousemove event的 DOM 物件不是.hero的情況下(this !== e.target)進行座標修正,只要滑鼠處於h1內部,就分別把(x,y)加上h1相對.hero左方和上方的距離。
| 1 | function shadow(e){ | 
接下來,我們要決定文字陰影實際上可以移動的距離和範圍。
宣告常數walk作為在(x,y)方向所能移動的最遠距離,這裡我們設為500,也就是向左或向右各250、向上或向下各250。
 const xWalk = Math.round((x / width * walk) - (walk / 2));,把.hero的中心點x 座標指定為0,x的範圍從-250~250(視窗最左邊到最右邊)。
 const yWalk = Math.round((y / height * walk) - (walk / 2));,把.hero的中心點y 座標指定為0,y的範圍從-250~250(視窗最上面到最下面)。
結合兩者,畫面上的座標 : 左上角(-250,-250)、正中央(0,0)、右下角(250,250)。
| 1 | const walk = 500; | 
- TextShadow能移動的範圍 (以walk = 500為例)
  
決定TextShadow可以移動的範圍後,接下來只要設定TextShadow的移動方向和顏色就完成囉!
| 1 | function shadow(e){ | 
補充資料:
contenteditable
[筆記] ES6: Destructuring Assignment 解構賦值的使用
JS一秒區分clientX,offsetX,screenX,pageX之間關係