第十六天挑战(鼠标拖影效果)
地址:https://javascript30.com/
所有内容均上传至gitee,答案不唯一,仅代表本人思路
中文详解:https://github.com/soyaine/JavaScript30
该详解是Soyaine及其团队整理编撰的,是对源代码的详解,强烈推荐大家观看学习!!!
本人gitee:https://gitee.com/thats-all-right-ha-ha/30-days—js-challenge
效果
-
样式分析
- 组件本体页面内居中(黑色),其他效果是组件的文本阴影
-
逻辑分析
-
阴影效果以组件中心点作为基准点向四周移动
-
阴影效果随着鼠标移动进行移动,对位的阴影效果向相反方向移动
-
本人代码及思路分析
仅提供布局及逻辑代码
结构:
<div class="hero">
<h1 contenteditable>🔥WOAH!</h1>
</div>
逻辑:
//设定横纵向初始值
let transverse = 0;
let direction = 0
//获取鼠标偏移量
let iniX = 0
let iniY = 0
const title = document.querySelector('h1')
document.addEventListener('mousemove', (e) => {
iniX = e.clientX - title.offsetLeft - title.offsetWidth / 2
iniY = e.clientY - title.offsetTop - title.offsetHeight / 2
direction = iniY / 2
transverse = iniX / 2
title.style.textShadow = `${transverse}px ${direction}px 0 rgba(255, 0, 255, 0.7), ${-transverse}px ${-direction}px 0 rgba(0, 255, 255, 0.7), ${-direction}px ${transverse}px 0 rgba(0, 255, 0, 0.7) , ${direction}px ${-transverse}px 0 rgba(0, 0, 255, 0.7)`
})
分析:
-
**整体思路:**这里监听了整个dom对象的鼠标移动事件,以鼠标移动距离为偏移量,给中心组件动态添加textShadow样式
-
具体实现:
- 首先选定需要监听和修改的元素
- 由于这里监听的是根Dom,根Dom的位移基准点在页面最左上角,获取组件中心点的位置作为偏移量,将clientX的起始点初始化至组件的中心
- 由于clientX是只读属性,所以这里的修改只是通过增加偏移量实现的伪修改
- 将修改后的clientX和clientY的值进行处理,作为组件阴影效果移动的值。
- 添加textShadow样式
-
弊端分析(与官方方法对比):
- 性能问题:监听了整个文档的
mousemove
事件,当鼠标移动时会频繁地触发事件处理函数,可能导致性能问题,尤其是在页面元素较多或复杂的情况下。 - 硬编码:阴影效果的计算是硬编码在JavaScript中的,如果标题文字的样式或布局发生变化,需要手动调整计算阴影的逻辑,不够灵活。
- 重复计算:每次鼠标移动都重新计算阴影效果的位置,即使鼠标移动的距离很小,也会触发整个计算和样式更新的过程,这样的重复计算可能会影响性能。
- 性能问题:监听了整个文档的
官方代码
官方代码仅代表该案例原作者思路,不唯一
结构
<div class="hero">
<h1 contenteditable>🔥WOAH!</h1>
</div>
逻辑
const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');
const walk = 500; // 500px
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 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);
分析
仅代表本人对该代码的分析
建议直接去看Soyaine的中文详解
-
**整体思路:**整体思路与上述保持一致
-
具体实现:
- 这里先获取了组件的高度和宽度,其次获取了鼠标的偏移量
- 第二步判断了鼠标事件是否是在hero元素中,如果鼠标在组件内移动,则切换偏移量的计算方式
- 偏移量的计算方式:
- 通过比值的方式,在文字组件中映射鼠标移动的距离,通过这个比值和最大范围数进行相乘并减最大范围的一半,作为移动的距离
-
优点:
- 更高效的事件处理:代码只监听了
.hero
元素的mousemove
事件,而不是整个文档,这样可以减少事件处理函数的触发次数,提高性能。 - 更精简的阴影计算逻辑:通过使用解构赋值和简洁的计算,将阴影效果的计算逻辑简化了,使代码更易读、更易维护。
- 更灵活的阴影效果:阴影效果的移动距离通过
walk
变量控制,可以通过修改这个变量来调整阴影的移动范围,增加了代码的灵活性。
- 更高效的事件处理:代码只监听了