JS 30 是由加拿大的全端工程師 Wes Bos 免費提供的 JavaScript 簡單應用課程,課程主打 No Frameworks
、No Compilers
、No Libraries
、No Boilerplate
在30天的30部教學影片裡,建立30個JavaScript的有趣小東西。
另外,Wes Bos 也很無私地在 Github 上公開了所有 JS 30 課程的程式碼,有興趣的話可以去 fork 或下載。
製作讓文字陰影跟著滑鼠一起移動的效果。
在.hero
內放入我們預計要用來產生文字陰影(Text Shadow)效果的文字(h1
)。
h1
上有一個特殊的屬性:contenteditable
,表示<h1></h1>
之間的內容是可以被修改的。
<div class="hero">
<h1 contenteditable>?WOAH!</h1>
</div>
<h1></h1>
之間的內容可被修改如下:
修改前
修改後
在實作文字陰影效果之前,我們要先取得.hero
和內部的h1
。
const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');
由於我們的目的是產生文字陰影隨著滑鼠移動的效果,所以在.hero
上註冊mousemove 事件
的監聽器並以shadow()
進行事件處理。
hero.addEventListener('mousemove',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;
這種較繁瑣的寫法。
function shadow(e){
//const width = hero.offsetWidth;
//const height = hero.offsetHeight;
const { offsetWidth: width, offsetHeight: height} = hero;
//where the person's cursor was
//let x = e.offsetX;
//let y = e.offsetY;
let { offsetX: x, offsetY: y} = 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
左方和上方的距離。
function shadow(e){
/*上略...*/
//if hovering h1 instead of hero, then modify the x and the y values
if (this !== e.target){
x = x + e.target.offsetLeft;
y = y + e.target.offsetTop;
}
}
接下來,我們要決定文字陰影實際上可以移動的距離和範圍。
宣告常數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)
。
const walk = 500;
function shadow(e){
/*上略...*/
//how far the text shadow should actually go
const xWalk = Math.round((x / width * walk) - (walk / 2));
const yWalk = Math.round((y / height * walk) - (walk / 2));
}
walk = 500
為例)決定TextShadow
可以移動的範圍後,接下來只要設定TextShadow
的移動方向和顏色就完成囉!
function shadow(e){
/*上略...*/
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)
`;
}
contenteditable
[筆記] ES6: Destructuring Assignment 解構賦值的使用
JS一秒區分clientX,offsetX,screenX,pageX之間關係