🎯 项目目标:
当鼠标在页面移动时,小圆点会跟随鼠标移动的位置,带有平滑动画。
🧠 实现思路:
-
HTML:
- 页面内放一个
div
作为圆点。
- 页面内放一个
-
CSS:
-
圆点使用绝对定位,初始在屏幕角落。
-
添加
transition
,让位置平滑过渡(非瞬移)。 -
设置宽高、颜色(或图片样式)。
-
-
JavaScript:
-
监听
mousemove
事件。 -
在事件中获取鼠标
clientX/clientY
。 -
设置圆点的位置为鼠标位置附近。
-
HTML 部分结构:
html
<div class="dot"></div>
实践代码如下::
初版JS(一个圆点的效果) :
javascript
const dot = document.getElementsByClassName('dot')
document.addEventListener('mousemove', (event) => {
console.log(event.clientX);
const x = event.clientX
const y = event.clientY
dot[0].style.top = ${y - 12.5}px
dot[0].style.left = ${x -12.5}px
})
CSS:
css
.dot {
position: absolute;
top: 0;
left: 0;
transition: all .2s ease;
width: 25px;
height: 25px;
border-radius: 50%;
background: yellowgreen;
};
进阶:添加拖尾效果(多个小点形成"尾巴")
JS(多个圆点形成一个小尾巴的效果):
javascript
const dots = document.querySelectorAll('.dot')
let positions = Array.from({ length: dots.length }, () => ({ x: 0, y: 0 }));
document.addEventListener('mousemove', (event) => {
const { clientX: x, clientY: y } = event
// 把当前位置放在队列前面
positions.unshift({ x, y })
positions.length = dots.length
// 每个圆点移动到对应的位置
dots.forEach((dot, i) => {
dot.style.left = positions[i].x + 'px'
dot.style.top = positions[i].y + 'px'
dot.style.opacity = 1 - i * 0.1
dot.style.transform = `scale(${1 - i * 0.05})`
})
})
CSS:
css
.dot {
position: absolute;
top: 0;
left: 0;
width: 25px;
height: 25px;
border-radius: 50%;
background: yellowgreen;
pointer-events: none;
transition: top 0.2s, left 0.2s;
}
页面效果展示:

额外知识记录:
✅ 关于多个圆点形成小尾巴的实现思路
1. 每次鼠标移动时:记录当前位置。
- 用
positions.unshift({ x, y })
把当前坐标放进数组开头,代表"最新"的位置。
2. 遍历每个圆点,让它去"追赶"对应的历史鼠标位置。
-
第一个圆点移动到最新的位置,
-
第二个圆点移动到稍早前的位置,
-
依此类推,制造出延迟感的拖尾效果。
✅ 关于为什么要给圆点加
pointer-events: none;
作用:让这个元素不响应鼠标事件。
你设置了 .dot
是鼠标指针跟随的小圆点,如果不给它加 pointer-events: none
,你鼠标碰到它时就会"碰撞"上它(即便你看不出来),这样就会阻碍 mousemove
的监听。
🔹1.为什么不加上 pointer-events: none会阻碍 mousemove 的监听?
鼠标一旦停在 .dot
元素上:
- 浏览器会把
mousemove
事件发送给.dot
元素本身; - 如果你并没有给
.dot
元素绑定mousemove
,事件就"断了", document
上的回调不再触发,拖尾停止更新,看起来就像"卡住"。
总结
虽然你现在的代码运行良好,肉眼可能看不出有什么卡顿,但养成加上
pointer-events: none
的习惯是更稳妥的。
✅ 关于
const positions = Array.from({ length: dots.length }, () => ({ x: 0, y: 0 }))
🔹1. dots.length
是多少?
dots
是多个拖尾小圆点的 DOM 元素集合,例如:
javascript
const dots = document.querySelectorAll('.dot');
所以 dots.length
表示你想要多少个"尾巴"。
🔹2. Array.from({ length: dots.length }, ...)
是什么?
这是 Array.from
的一个常见用法,语法是:
javascript
Array.from({ length: N }, (value, index) => ...)
意思是:创建一个长度为 N 的数组,并用后面的函数生成每一项。
🔹3. 为什么要写成 { length: dots.length }
?
因为 Array.from
的第一个参数可以是一个"类数组对象"(只要有 .length
属性就行),比如:
javascript
Array.from({ length: 3 }) → [undefined, undefined, undefined]
🔹4. 回调函数 () => ({ x: 0, y: 0 })
是干嘛的?
这个函数的作用是:为数组中的每一项都返回一个初始坐标对象 { x: 0, y: 0 }
。
也就是说:
javascript
Array.from({ length: 3 }, () => ({ x: 0, y: 0 }));
// 结果是:
[
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 }
]
🔹5. 为什么这么写有必要?
这个 positions
数组的作用是:
记录每一个尾巴圆点当前的位置。后续我们会用它来移动 .dot
的位置,实现拖尾轨迹。如果你有 10 个小圆点,就需要一个 10 项的数组,每一项都记录这个圆点的位置。
总结
这行代码的含义就是:
"为每个
.dot
小圆点初始化一个位置对象 { x: 0, y: 0 },构成一个统一的positions
数组,用于后续跟随鼠标拖尾。"
✅ 关于
dot.style.opacity = 1 - i * 0.1;dot.style.transform = `scale(${1 - i * 0.05})`
这是给拖尾点添加视觉渐变 和缩放的效果:
-
opacity = 1 - i * 0.1
-
第 0 个点透明度是
1
(完全不透明) -
第 1 个点是
0.9
-
第 2 个点是
0.8
... -
后面的点越来越透明
-
-
scale = 1 - i * 0.05
-
第 0 个点大小是
1
(原始大小) -
第 1 个点是
0.95
-
第 2 个点是
0.90
... -
后面的点越来越小
-
总结
就是:"实现前面圆点大且亮,后面越来越小、越来越淡的尾巴效果。"