运维门户中心是一个集组织管理、应用管理、栏目订阅等功能的综合平台,登录界面一直比较朴素,为了美化登录界面需要选取背景。参考了一些线上门户的登录背景,比如Google的背景是用svg写的,知乎是用canvas写的。比较起来,canvas写的动画视觉效果更好,决定学习下知乎背景的写法。
整体思路
获取画布渲染上下文,生成制定个数的随机坐标点,给每个点不同的初始速度使之运动。在两两点之间建立联系,给连线一个透明度值,使两点越近连线越明显,以符合日常生活经验。根据速度改变坐标,遇到屏幕边界时,做穿越或碰撞处理。在浏览器重绘之前更新画布。
核心分解
html内容只有一行<canvas id="myCanvas"></canvas>,<canvas> 是 HTML5 新增的元素,可通过JavaScript脚本来绘制图形。它的用途广泛,可用于绘制图形,制作照片,创建动画,甚至可以进行实时视频处理或渲染。下面来分解js的内容。
canvas基础
<canvas>标签只有两个属性,width与height,这里通过DOM properties设置了宽度和高度。canvas起初是空白的,为了展示,脚本要先找到渲染上下文(the rendering context),然后在它上面绘制。<canvas>元素的getContext()方法是用来获取渲染上下文和它的绘画功能,传入的参数”2d”是上下文的格式。
接下来是定义圆形的半径,取[5,20]范围,初始位置在不出画布的前提下随机,初始水平速度与垂直速度在[-0.4,0.4]范围内。代码如下: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
28var w = window.innerWidth;
var h = window.innerHeight;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var allRound = [];
var dxdy = [];
//设置画布宽高与窗口宽高一样
canvas.width = w;
canvas.height = h;
function fnRandom(min, max) {
return parseInt((max - min) * Math.random() + min + 1);
}
function Round() {
this.r = fnRandom(5, 20);
this.diam = this.r * 2;
//随机位置
var x = fnRandom(0, canvas.width - this.r);
this.x = x < this.r ? this.r : x;
var y = fnRandom(0, canvas.height - this.r);
this.y = y < this.r ? this.r : y;
//随机速度
var speed = fnRandom(2, 4) / 10
this.speedX = fnRandom(0, 4) > 2 ? speed : -speed;
this.speedY = fnRandom(0, 4) > 2 ? speed : -speed;
//颜色
this.color = "#ECEEEF";
}
路径绘制的方法
Round有两个方法draw与move,draw方法是绘制圆形,这里介绍下使用路径绘制图形的步骤:
- 首先,创建路径的起始点。
- 使用画图命令画出路径。
- 把路径封闭。
- 可通过描边或填充路径区域来渲染图形。
以下是用到的函数:
beginPath()新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。closePath()闭合路径之后图形绘制命令又重新指向到上下文中。stroke()通过线条来绘制图形轮廓。fill()通过填充路径的内容区域生成实心的图形。
move方法是圆形从现有坐标上移动一个水平和垂直位移。提供圆形到达画布边界的处理方案:如果圆形碰到右侧边界,则水平速度取反向,模拟碰撞反弹的效果;如果圆形碰到左侧边界,则将圆形置于画布右侧,模拟圆形穿过左侧边界的效果。画布的下边界与上边界也分别模拟碰撞反弹与穿越效果。代码如下:
1 | Round.prototype.draw = function() { |
动画基本步骤
roundMove()是核心部分,是它让动画动了起来,先看下动画的基本步骤:
- 清空canvas 这里用
clearRect方法实现。 - 保存canvas状态 如果你要改变一些会改变canvas状态的设置,又要在每画一帧之时都是原始状态则要先保存。
- 绘制动画图形 这一步是重绘动画帧。这里用到的是
window.requestAnimationFrame(callback),这个方法提供了平缓有效率的方式执行动画,当系统准备好重绘条件的时候次啊会调用绘制动画帧,在重绘之前浏览器执行函数roundMove。 - 恢复canvas状态 如果已保存了canvas状态,可以先恢复,再重绘下一帧。
1 | //使用Round |
roundMove()中逐个生成圆形,且和在此之前生成的圆形两两之间连线,连线为黑色,rgba的最后一个参数用来设置透明度。如果不设置透明度,则默认透明度为1,则可以看到所有的连线。这里计算了两个圆形之间的距离l,透明度设置在(0,0.03]之间。距离越大,透明度越高,连线就越不清晰。距离一定远之后,看起来两个圆形就是离散的了。连线使用的就是路径绘制的方法。最后实现的效果,可以在运维门户中心的登录页面看到,传送门: http://10.142.90.58:9092/#/
参考资料
- 一个很好的canvas教程:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API
- w3cSchool的canvas教程:http://www.w3school.com.cn/jsref/dom_obj_canvas.asp
事实上,知乎的登录页背景是直接用了particles.js库实现的,下面是相关教程:
- particles的demo:https://codepen.io/VincentGarreau/pen/pnlso
- particles的github:https://github.com/VincentGarreau/particles.js