引言
一个很经典的特效,花了一点时间自己手动写了一个,先上图:
详细代码
html
<canvas id="canvas_bg"></canvas>
css
html, body {
height: 100%;
padding: 0;
margin: 0;
}
#canvas_bg {
display: block;
}
javascript
class circle {
constructor(num) {
this.canvas = document.getElementById('canvas_bg');
this.canvas.width = document.documentElement.clientWidth;
this.canvas.height = document.documentElement.clientHeight;
this.ctx = this.canvas.getContext('2d');
// 创建随机状态小球
this.arr = Array.from(new Array(num)).map(item => ({
x: Math.random() * this.canvas.width,
y: Math.random() * this.canvas.height,
speed: Math.random() * 1.5 + 0.5,
xDir: Math.random() > 0.5 ? -1:1,
yDir: Math.random() > 0.5 ? -1:1,
r: 2
}))
// 小球连线距离
this.dist = 100
this.animation()
window.onresize = ()=> {
this.canvas.width = document.documentElement.clientWidth;
this.canvas.height = document.documentElement.clientHeight;
}
}
// 计算小球位置并判断方向与绘制
drawCircle() {
this.arr.forEach(item => {
item.x += item.xDir * item.speed
item.y += item.yDir * item.speed
item.x <= 0 && (item.xDir = 1)
item.x > this.canvas.width - 1 && (item.xDir = -1, item.x = this.canvas.width - 1)
item.y <= 0 && (item.yDir = 1)
item.y > this.canvas.height - 1 && (item.yDir = -1, item.y = this.canvas.height - 1)
this.ctx.beginPath();
this.ctx.arc(item.x, item.y, item.r, 0, 2 * Math.PI);
this.ctx.fill();
})
}
// 计算连线距离内的小球
calcLine() {
var arr = this.arr.concat()
this.lineArr = []
for(var i = 0,len = arr.length; i < len; i++){
for(let y = i+1; y < len; y++){
let val = Math.sqrt(Math.pow(arr[i].x - arr[y].x, 2) + Math.pow(arr[i].y - arr[y].y, 2) ,2);
if(val < this.dist){
this.lineArr.push({
start: arr[i],
end: arr[y],
val: val,
ratio: (val / this.dist)
})
}
}
}
}
// 绘制链接线条
drawLine() {
while(this.lineArr.length){
this.ctx.beginPath()
let item = this.lineArr.shift();
let c = 255 * item.ratio
this.ctx.strokeStyle = `rgb(${c},${c},${c})`
this.ctx.moveTo(item.start.x, item.start.y)
this.ctx.lineTo(item.end.x, item.end.y);
this.ctx.stroke();
}
}
// 动画过渡
animation() {
this.canvas.width = this.canvas.width
this.drawCircle()
this.calcLine()
this.drawLine()
setTimeout(() => {
this.animation()
}, 30)
}
}
var circleObj = new circle(100);
demo演示
解释
这个动画整体效果其实很简单,画布初始化什么的就不说了。
1.首先创建一些随机状态的小球,有位置、移动方向、移动速率等
2.通过双层循环判断每个小球之间的距离(就用初中学的勾股定理,直角三角形两边的平方和等于斜边的平方,斜边就是小球距离),符合条件的(我设置的小于100)都存起来
3.最后绘制小球与线条,加上动画渲染(我这里每隔30毫秒渲染一次,每次渲染都要重新计算上面提到的参数)
结语
详细看看上方的demo中演示与代码,代码量很少,理解起来也不难,只要你有初中知识就能理解。
以上如有问题或疏漏,欢迎指正