0%

JavaScript几何星空连线(鼠标跟随)完善

完善了一下星空连线背景效果. 添加了粒子的鼠标跟随的效果. 参考的类似功能的JS源码都处理压缩过, 没有换行缩进, 变量名都是a, b, c... 看着真累啊.

把两次遍历改成了一次遍历, 把鼠标所在的点 p0points 数组 concat 到一起处理了.

舍弃了原来按时间间隔计算移动距离的方法, 直接每一帧移动一定距离. 优化了代码, 提高了些性能.

鼠标跟随的原理是, 当粒子靠近鼠标指针到一定距离区间内, 就每帧向鼠标靠近对应距离. 所以当粒子一边远离一边被吸引时在边界会有些许鬼畜.

点此访问演示DEMO

截图:

演示图片
演示图片

源码:

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//==========================================
// File: background.js
// Title: 星空连线(鼠标跟随)
// Auther: XieNaoban
// Version: v1.1
// Note: 直接扔在<body>里
//==========================================

// 可调参数
var BACKGROUND_COLOR = "rgba(0,43,54,1)"; // 背景色
var POINT_NUM = 99; // 屏幕上点的数目
var POINT_COLOR = "rgba(255,255,255,0.7)"; // 点的颜色
var LINE_LENGTH = 10000; // 点之间连线长度(的平方)

// 创建背景画布
var cvs = document.createElement("canvas");
cvs.width = window.innerWidth;
cvs.height = window.innerHeight;
cvs.style.cssText = "\
position:fixed;\
top:0px;\
left:0px;\
z-index:-1;\
opacity:1.0;\
";
document.body.appendChild(cvs);

var ctx = cvs.getContext("2d");

var startTime = new Date().getTime();

//随机数函数
function randomInt(min, max) {
return Math.floor((max - min + 1) * Math.random() + min);
}

function randomFloat(min, max) {
return (max - min) * Math.random() + min;
}

//构造点类
function Point() {
this.x = randomFloat(0, cvs.width);
this.y = randomFloat(0, cvs.height);

var speed = randomFloat(0.3, 1.4);
var angle = randomFloat(0, 2 * Math.PI);

this.dx = Math.sin(angle) * speed;
this.dy = Math.cos(angle) * speed;

this.r = 1.2;

this.color = POINT_COLOR;
}

Point.prototype.move = function () {
this.x += this.dx;
if (this.x < 0) {
this.x = 0;
this.dx = -this.dx;
} else if (this.x > cvs.width) {
this.x = cvs.width;
this.dx = -this.dx;
}
this.y += this.dy;
if (this.y < 0) {
this.y = 0;
this.dy = -this.dy;
} else if (this.y > cvs.height) {
this.y = cvs.height;
this.dy = -this.dy;
}
}

Point.prototype.draw = function () {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}

var points = [];

function initPoints(num) {
for (var i = 0; i < num; ++i) {
points.push(new Point());
}
}

var p0 = new Point(); //鼠标
p0.dx = p0.dy = 0;
var degree = 2.5;
document.onmousemove = function (ev) {
p0.x = ev.clientX;
p0.y = ev.clientY;
}
document.onmousedown = function (ev) {
degree = 5.0;
p0.x = ev.clientX;
p0.y = ev.clientY;
}
document.onmouseup = function (ev) {
degree = 2.5;
p0.x = ev.clientX;
p0.y = ev.clientY;
}
window.onmouseout = function () {
p0.x = null;
p0.y = null;
}

function drawLine(p1, p2, deg) {
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
var dis2 = dx * dx + dy * dy;
if (dis2 < 2 * LINE_LENGTH) {
if (dis2 > LINE_LENGTH) {
if (p1 === p0) {
p2.x += dx * 0.03;
p2.y += dy * 0.03;
} else return;
}
var t = (1.05 - dis2 / LINE_LENGTH) * 0.2 * deg;
ctx.strokeStyle = "rgba(255,255,255," + t + ")";
ctx.beginPath();
ctx.lineWidth = 1.5;
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.closePath();
ctx.stroke();
}
return;
}

//绘制每一帧
function drawFrame() {
cvs.width = window.innerWidth;
cvs.height = window.innerHeight;
ctx.fillStyle = BACKGROUND_COLOR;
ctx.fillRect(0, 0, cvs.width, cvs.height);

var arr = (p0.x == null ? points : [p0].concat(points));
for (var i = 0; i < arr.length; ++i) {
for (var j = i + 1; j < arr.length; ++j) {
drawLine(arr[i], arr[j], 1.0);
}
arr[i].draw();
arr[i].move();
}

window.requestAnimationFrame(drawFrame);
}

initPoints(POINT_NUM);
drawFrame();