实现知乎登录背景

知乎登录背景的实现


前戏

知乎作为程序员装逼和学会装备的利器,实属每天必逛之地,进来,我们就来模仿一下其登录背景的实现.

效果演示

实现原理

效果其实很简单,就是很多小圆用线互相连接,然后不断改变位置,线会随着距离改变其可视度,这里我们用canvas来实现,话不多说 开始撸

代码

HTML结构

<canvas id="cns"></canvas>

预置CSS

1
2
3
4
5
html,body{
width: 100%;
height: 100%;
overflow: hidden;
}

js效果实现

####常量声明

1
2
3
4
5
6
7
8
9
10
let Count=35;
let CircleArr=[];
let WIDTH=window.innerWidth,HEIGHT=window.innerHeight;
let canvas=document.getElementById('cns');
canvas.width=WIDTH;
canvas.height=HEIGHT;
let context=canvas.getContext('2d')
context.strokeStyle='rgba(0,0,0,0.04)';
context.strokeWidth=1;
context.fillStyle='rgba(0,0,0,0.08)';

这里我们定义了 35个小球 以及 用来装小球的容器,获取屏幕宽高 , 同时获取画笔,预设置画笔的属性,轻松加愉快 orz …

画小球

万物皆对象,注意对象又来了~

定义小球原型

1
2
3
4
5
6
7
8
function Circle(x,y,r,moveX,moveY) {
// x:小球x坐标, y: y坐标,r:半径,moveX:x方向移动速度,moveY:y方向移动速度
this.x=x;
this.y=y;
this.r=r;
this.moveX=moveX;
this.moveY=moveY;
}

画球

1
2
3
4
5
6
7
8
function drawCircle(ctx,x,y,r,moveX,moveY) {
let circle=new Circle(x,y,r,moveX,moveY);
ctx.beginPath();
ctx.arc(circle.x,circle.y,circle.r,0,2*Math.PI)
ctx.closePath()
ctx.fill();
return circle
}

同样的原理 画出小球之间的连线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Line(x, y, _x, _y, o) {
// x,y分别为起点x,y坐标,_x,_y分别为终点坐标,o为透明度度
this.x=x;
this.y=y;
this._x=_x;
this._y=_y;
this.o=o
}
function drawLine(ctx, x, y, _x, _y, o) {
let line = new Line(x, y, _x, _y, o)
ctx.beginPath()
ctx.strokeStyle = 'rgba(0,0,0,'+ o +')'
ctx.moveTo(line.x, line.y)
ctx.lineTo(line._x, line._y)
ctx.closePath()
ctx.stroke();
}
初始化canvas方法init()
1
2
3
4
5
6
7
8
9
10
11
12
13
//辅助函数num()获取随机变量
function num(maxValue, minValue) {
let min=arguments[1]||0;
let max=maxValue;
return Math.floor(Math.random()*(max-min))+min
}
function init() {
//初始化小球 并且将小球装进容器CircleArr 便于draw()里面调用
for(let i=0;i<Count;i++){
CircleArr.push(drawCircle(context,num(WIDTH),num(HEIGHT),num(15,2),num(10,-10)/40,num(10,-10)/40))
}
draw()
}
负责绘画出整个场景draw()
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
function draw() {
context.clearRect(0,0,WIDTH,HEIGHT);
// 清空画布
for(let i = 0 ;i<Count;i++){
// 根据arr里面的小球数据绘制小球
drawCircle(context,CircleArr[i].x,CircleArr[i].y,CircleArr[i].r)
}
for (let i = 0; i < Count; i++) {
for (let j = 0; j < Count; j++) {
// 双重for循环绘制小球之间的连线
if (i + j < Count&&i !== j&&i!==(i+j)) {
// i + j < Count来避免重复画线 i !==j、i!==(i+j)避免自己和自己画线
let X=Math.abs(CircleArr[i+j].x-CircleArr[i].x)
let Y=Math.abs(CircleArr[i+j].y-CircleArr[i].y)
获取 小球之间的直线距离
let dis=Math.sqrt(X*X + Y*Y);
let C=1/dis*7-0.009;
// 距离越远透透明度越低
let opacity=C>0.03?0.03:C;
if(opacity>0){
drawLine(context,CircleArr[i].x,CircleArr[i].y,CircleArr[i+j].x,CircleArr[i+j].y,opacity)
}
}
}
}
}
不断重绘,让小球动起来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
window.onload=function () {
init()
setInterval(
function () {
for(let i=0;i<Count;i++){
let circle=CircleArr[i];
circle.x+=circle.moveX;
circle.y+=circle.moveY;
if(circle.x>WIDTH){
circle.x=0
}else if(circle.x<0){
circle.x=WIDTH
}
if(circle.y>HEIGHT){
circle.y=0
}else if(circle.y<0)(
circle.y=HEIGHT
)
}
draw()
},16)
}

至此高逼格的知乎门面就被我们搞定一丢丢了,知乎是前端学习的榜样,大家要像窑子一样多逛它。代码地址,欢迎戳戳戳