JS30-16-Mouse-Move-Shadow

滑鼠移動時,讓文字的陰影跟著移動。

目標

  • 滑鼠移動時,讓文字的陰影跟著移動。

實踐步驟

  1. 取得取得文字區域的元件

  2. 監聽 mousemove

    • 取得 hero 的 寬、高
    • 取得滑鼠的座標
    • 計算位置與比例,修改textShadow屬性值

成品

[DEMO] | [GitHub]


JS學習紀錄

此次重點在於

  1. 座標點的取得以及計算
  2. 解構賦值的運用
HTML
1
2
3
<div class="hero">
<h1 contenteditable>🇹🇼 Taiwan!</h1>
</div>
全部js程式碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');
const walk = 100; //設定 text-shadow 座標最大的偏移範圍

function shadow(e){
// console.dir(hero);

// 取得 hero 的 寬、高
// const width = hero.offsetWidth;
// const height = hero.offsetHeight;
/* 可簡寫如下 */
const {offsetWidth: width, offsetHeight: height} = hero;

// 取得滑鼠的座標
// offsetX與offsetY回傳的座標,是以「目前DOM box model區塊範圍」為主,
// 回傳滑鼠座標位於「目前的DOM區塊範圍」的哪裡,
// 而不是以整個「window」為主,另外DOM與DOM重疊的話,依舊是分開計算。
// 註:起點為左上角: x:0 , y:0 ,向右增加 x ,向下增加 y
let {offsetX: x, offsetY: y} = e;
// console.log(x, y);

// 若滑鼠從父元素移到子元素的話,offsetX與offsetY會 歸0 重新計算,
// 所以需要將父元素與子元素之間座標的落差補足。
if (this !== e.target){
// console.dir(e.target);
x = x + e.target.offsetLeft; // 目前DOM之滑鼠的X座標 + 目前DOM位於父元素的X座標
y = y + e.target.offsetTop; // 目前DOM之滑鼠的Y座標 + 目前DOM位於父元素的Y座標
}
// console.log(x, y);

// (座標在hero的比例 * 最大偏移量的值) - (一半的最大偏移量的值)
// 取得 正值或負值 的座標,如: 最大偏移量的值=100,取得範圍落於 -50~50 之間
const xWalk = Math.round((x / width * walk) - (walk / 2));
const yWalk = Math.round((y / height * walk) - (walk / 2));


text.style.textShadow = `
${xWalk}px ${yWalk * -0.7}px 0 rgba(255,0,0,0.3),
${xWalk * -1}px ${yWalk}px 0 rgba(0,255,0,0.3),
${yWalk}px ${xWalk * -0.5}px 0 rgba(0,255,255,0.3),
${yWalk * -1}px ${xWalk}px 0 rgba(0,0,255,0.3)
`;

}

// 監聽滑鼠事件
hero.addEventListener('mousemove', shadow);

解構賦值(Destructuring assignment)

從上面程式碼,將使用「解構賦值」的地方,額外拉出來

解構賦值
1
2
3
4
5
// 取得 hero 的 寬、高
const width = hero.offsetWidth;
const height = hero.offsetHeight;
// 可簡寫如下
const {offsetWidth: width, offsetHeight: height} = hero;
解構賦值
1
2
3
4
let x = e.offsetX;
let y = e.offsetY;
// 可簡寫如下
let {offsetX: x, offsetY: y} = e;