效果图

MouseMoveEffect

具体效果请参考这个页面

思路

事件绑定

方法为:document.addEventListener(event, function, useCapture);

event为描述事件名称的字符串。

function为事件发生后触发执行的函数,当事件触发时,事件对象会作为第一个参数传入函数中。

useCapture为可选,默认为假的布尔值参数,true时事件句柄在捕获阶段执行,false时在冒泡阶段执行

  • 鼠标移动事件
1
document.addEventListener("mousemove", myFunction);

当然,为了兼容手机端,也要绑定点击事件

  • 点击事件
1
2
document.addEventListener("touchmove", myFunction);
document.addEventListener("touchstart", myFunction);

元素

  • 声明一个类,鼠标移动时实例化为拖尾元素;
  • 元素实例化后进行初始化,元素属性要包括元素坐标,样式,颜色和速度,还有存活时间;
  • 元素还要有个Update函数,根据速度计算出下一帧的坐标位置。根据剩余存活时间计算出缩放大小;
  • 元素需要有一个销毁眼熟,当存活时间小于等于0的时候调用;

主循环

  • 在鼠标移动时,每个循环在鼠标位置生成一个元素并初始化;
  • 每个生成的元素都存在数组中,每个循环遍历所有数组元素进行Update,并进行渲染;
  • 当元素存活时间小于等于0时,调用销毁函数,并将此元素移除数组;

通过计时器进行循环:setInerval(code, millisec)

1
setInterval(function (), 1000 / 60);

因为时间以毫秒计数,所以如果一秒要刷新60帧则时间为1000 / 60;

特效

  • 使用Math.random() 达成随机颜色和随机样式;

完整代码

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//鼠标移动特效
(function () {
var colors = ["#D61C59", "#E7D84B", "#1B8798"];
characters = ["♬", "♪"];
elementGroup = [];
//定义元素类
class Element {
//构造函数
constructor() {
num = Math.floor(Math.random() * characters.length);
this.character = characters[num];
this.lifeSpan = 120;
this.initialStyles = {
position: "fixed",
top: "0",
display: "block",
pointerEvents: "none",
"z-index": "10000000",
fontSize: "25px",
"will-change": "transform",
color: "#000000"
};
//初始化
this.init = function (x, y, color) {
this.velocity = { x: (Math.random() < .5 ? -1 : 1) * (Math.random() / 2), y: 1 };
this.position = { x: x - 10, y: y - 20 };
this.initialStyles.color = color;
this.element = document.createElement("span");
this.element.innerHTML = this.character;
ApplyStyle(this.element, this.initialStyles);
this.update();
document.body.appendChild(this.element);
};
//更新
this.update = function () {
//移动,缩放
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
this.lifeSpan--;
this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px,0) scale(" + this.lifeSpan / 120 + ")";
};
//销毁
this.die = function () {
this.element.parentNode.removeChild(this.element);
};
}
}

AddListener();
//循环
setInterval(
function () {
Rander();
},
1000 / 60);
//添加事件监听器
function AddListener() {
//当前事件对象会作为第一个参数传入函数
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("touchmove", Touch);
document.addEventListener("touchstart", Touch);
}
//逐个渲染
function Rander() {
for (var i = 0; i < elementGroup.length; i++) {
elementGroup[i].update();
if (elementGroup[i].lifeSpan < 0) {
elementGroup[i].die();
elementGroup.splice(i, 1);
}
}
}
//鼠标移动事件函数
function onMouseMove(t) {
num = Math.floor(Math.random() * colors.length);
CreateElement(t.clientX, t.clientY, colors[num]);
}
//添加元素
function CreateElement(x, y, color) {
var e = new Element;
e.init(x, y, color);
elementGroup.push(e);
}
//调整元素属性
function ApplyStyle(element, style) {
for (var i in style) {
element.style[i] = style[i];
}
}
//触摸事件函数
function Touch(t) {
if (t.touches.length > 0) {
for (var i = 0; i < t.touches.length; i++) {
num = Math.floor(Math.random() * r.length);
s(t.touches[i].clientX, t.touches[i].clientY, r[num]);
}
}
}
})();

Cover