iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
自我挑戰組

JavaScript 30天挑戰 自學筆記系列 第 16

JS30 自學筆記 Day16_CSS Text Shadow Mouse Move Effect

  • 分享至 

  • xImage
  •  

今日任務: 跟著滑鼠位移大小,產生不同大小的陰影

取得滑鼠位置

為了知道位移大小,先取得滑鼠位置

offsetWidth / offsetHeight

offsetWidth、offsetHeight: 「元素本身」的寬度/高度,並完整了包含了邊界、捲軸及padding。

取得hero的寬高

const hero = document.querySelector('.hero');
const width = hero.offsetWidth;
const height = hero.offsetHeight;

物件的解構賦值

詳細說明可以看這邊

前面程式可以簡寫成:

const hero = document.querySelector('.hero');
const { offsetWidth: width, offsetHeight: height } = hero;

offsetX / offsetY

offsetXoffsetY: 指滑鼠到外層容器的距離
滑鼠在文字外的時候,位置為(e.offsetX, e.offsetY)(滑鼠到外層容器的距離)
點擊綠色位置會是(0,0)
點擊紫色位置會是(342,360)
在文字h1內的時候
點擊藍色位置又會是(0,0)

offsetLeft / offsetTop

Day13時,有學過
offsetLeft/offsetTop: 元素本身相對於母元素的水平/垂直距離。

this 和 e.target 差異

  • e.target: 觸發事件的元素
  • this: 被監聽的對象本身,也就是 element.addEventListener() 的 element。

在今天的例子中,e.target是滑鼠所在位置的元素(可能是hero或h1),this則是監聽對象hero

當滑鼠點到hero(h1外的範圍),滑鼠位置為
(e.offsetX, e.offsetY)
當滑鼠點到h1時,滑鼠位置為
(e.offsetX + e.target.offsetLeft, e.offsetY + e.target.offsetTop)

const hero = document.querySelector('.hero');
const text = document.querySelector('h1');
hero.addEventListener('mousemove', shadow);

function shadow(e) {
    const { offsetWidth: width, offsetHeight: height } = hero;
    let { offsetX: x, offsetY: y } = e;

    if (this !== e.target) {
        x = x + e.target.offsetLeft;
        y = y + e.target.offsetTop;
    }
}

陰影大小

所以陰影應該要多少呢,這邊設300(越大陰影就越遠)

const walk = 300; //300px

以畫面中心為原點

(x / width)為滑鼠x位移大小相對於hero寬度的百分比
(y / height)為滑鼠y位移大小相對於hero高度的百分比
再乘上walk,得到陰影位移大小

原點在左上角(0,0),想改以畫面中心為原點,所以要/2
本來陰影位移是0到100,變成-50到50(正負座標都能移動)

function shadow(e) {
    const { offsetWidth: width, offsetHeight: height } = hero;
    let { offsetX: x, offsetY: y } = e;

    if (this !== e.target) {
        x = x + e.target.offsetLeft;
        y = y + e.target.offsetTop;
    }
    const XWalk = (x / width) * walk - walk / 2;
    const YWalk = (y / height) * walk - walk / 2;
    console.log(XWalk, YWalk);
}

數值太長

用Math.round取整數

Math.round() 會回傳四捨五入後的整數

const XWalk = Math.round((x / width) * walk - walk / 2);
const YWalk = Math.round((y / height) * walk - walk / 2);

將數值放上陰影css

text.style.textShadow = `${XWalk}px ${YWalk}px 0 red`;

加上更多陰影與顏色

text.style.textShadow = 
`${XWalk}px ${YWalk}px 0 red,
${XWalk * -1}px ${YWalk * -1}px 0 green,
${YWalk}px ${XWalk}px 0 blue,
${YWalk * -1}px ${XWalk * -1}px 0 pink`;

完整原始碼

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

hero.addEventListener('mousemove', shadow);
    
function shadow(e) {
    const { offsetWidth: width, offsetHeight: height } = hero;
    let { offsetX: x, offsetY: y } = e;

    if (this !== e.target) {
        x = x + e.target.offsetLeft;
        y = y + e.target.offsetTop;
    }
    
    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 red,
    ${XWalk * -1}px ${YWalk * -1}px 0 green,
    ${YWalk}px ${XWalk}px 0 blue,
    ${YWalk * -1}px ${XWalk * -1}px 0 pink`;
}

今日學習到的:

  • offsetWidth / offsetHeight: 「元素本身」的寬度/高度,並完整了包含了邊界、捲軸及padding
  • offsetX / offsetY: 指到外層容器的距離
  • offsetLeft / offsetTop: 元素本身相對於母元素的水平/垂直距離。
  • e.target: 觸發事件的元素
  • this: 被監聽的對象本身,也就是 element.addEventListener() 的 element
  • Math.round() 會回傳四捨五入後的整數

效果連結:連結

參考連結:
pjchender:JavaScript ES6 中的物件解構賦值(object destructuring)
什麼是 clientHeight, clientWidth, offSetHeight, offsetWidth, scrollHeight, scrollWidth, scrollTop, scrollLeft
pjchender: this 和 e.target 在 eventHandler 中的差異


上一篇
JS30 自學筆記 Day15_LocalStorage and Event Delegation
下一篇
JS30 自學筆記 Day17_Sorting Band Names without articles
系列文
JavaScript 30天挑戰 自學筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言