canvas简单快速的实现知乎登录页背景效果


Posted in Javascript onMay 08, 2017

前言

打开知乎的登录页,就可以看到其背景有一个动效,看起来好像蛮不错的样子:

canvas简单快速的实现知乎登录页背景效果

这个效果使用canvas是不难实现的,接下来就一步一步地讲解并实现这个效果。

分析

在动工之前先分析这个效果到底是如何运动的。首先要理解的是虽然看起来好像所有线和圆都在运动,但实际上只有圆才是在运动的,而线只不过是把满足一定条件的任意两个圆连接在一起。那么接下来就分析圆是怎么运动的,从效果看,每个圆都是在做匀速直线运动,而且运动方向不一,通过物理相关知识可以得知,每一个圆在水平方向和垂直方向都有一个速度。最后是当圆运动出画布任一边界的时候,这个圆会从出边界的这条边的对边再次进入画布。把这三个关键点理解清楚了就清晰很多了。

实践

先创建一个canvas画布:

// 这里就简单地设置下背景色
<body style="background:#f7fafc;">
 <canvas id="canvas" style="width: 100%; height: 100%;"></canvas>
</body>

接着先获取canvas的上下文环境并设置一些共用的属性

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;

context.fillStyle = "rgba(0, 0, 0, 0.08)";
context.strokeStyle = "rgba(0, 0, 0, 0.05)";
context.lineWidth = 0.5;

接下来绘制圆,那么绘制圆需要圆的圆心坐标,半径,水平方向的速度,垂直方向的速度,并且这些信息要满足一定的条件,通过一个函数来创建:

// 存放所有圆的数组,这里用balls
var balls = [];
function createBall() {
 // x坐标
 var _x = Math.random() * canvas.width;
 // y坐标
 var _y = Math.random() * canvas.height;
 // 半径 [0.01, 15.01]
 var _r = Math.random() * 15 + 0.01;
 // 水平速度 [±0.0, ±0.5]
 var _vx = Math.random() * 0.5 * Math.pow( -1, Math.floor(Math.random() * 2 + 1) );
 // 垂直速度 [±0.0, ±0.5]
 var _vy = Math.random() * 0.5 * Math.pow( -1, Math.floor(Math.random() * 2 + 1) );
 // 把每一个圆的信息存放到数组中
 balls.push({
 x: _x,
 y: _y,
 r: _r,
 vx: _vx,
 vy: _vy
 });
}

然后根据自己的情况选择需要绘制多少个圆,这里我假设有20个,看起来舒服一点:

// 圆的数量
var num = 20;
for(var i = 0; i < num; i++) {
 createBall();
}

现在圆的信息都有了,下一步就是绘制每一帧的圆和线,创建一个render函数,然后在函数内先绘制所有的圆出来:

for(var k = 0; k < num; k++) {
 context.save();
 context.beginPath();
 context.arc( balls[k].x, balls[k].y, balls[k].r, 0, Math.PI*2 );
 context.fill();
 context.restore();
}

接着要遍历每两个圆的圆心之间的距离是否小于某个临界值(比如500),满足则将这两个圆的圆心连接起来:

for(var i = 0; i < num; i++) {
 for(var j = i + 1; j < num; j++) {
 if( distance( balls[i], balls[j] ) < 500 ) {
  context.beginPath();
  context.moveTo( balls[i].x, balls[i].y );
  context.lineTo( balls[j].x, balls[j].y );
  context.stroke();
 }
 }
}

这里的 distance 函数就是计算两点之间的距离:

function distance(point1, point2) {
 return Math.sqrt( Math.pow( (point1.x - point2.x), 2 ) + Math.pow( (point1.y - point2.y), 2 ) );
}

还有一步就是判断圆是否超出了边界值,若满足条件则从对边再次进来:

for(var k = 0; k < num; k++) {
 balls[k].x += balls[k].vx;
 balls[k].y += balls[k].vy;

 if( balls[k].x - balls[k].r > canvas.width ) {
 balls[k].x = 0 - balls[k].r;
 }
 if( balls[k].x + balls[k].r < 0 ) {
 balls[k].x = canvas.width + balls[k].r;
 }
 if( balls[k].y - balls[k].r > canvas.height ) {
 balls[k].y = 0 - balls[k].r;
 }
 if( balls[k].y + balls[k].r < 0 ) {
 balls[k].y = canvas.height + balls[k].r;
 }
}

当然如果想简单点,只要圆超出就移除并重新生成一个圆即可:

if( balls[k].x - balls[k].r > canvas.width || 
 balls[k].x + balls[k].r < 0 || 
 balls[k].y - balls[k].r > canvas.height || 
 balls[k].y + balls[k].r < 0) {
 balls.splice(k, 1);
 createBall();
}

这样每一帧绘制的细节就完成了,最后一步就是让圆都运动起来:

(function loop(){
 render();
 requestAnimationFrame(loop);
})();

到此,整个效果就出来了。当然这里面有很多细节可以自己琢磨琢磨,让这个效果变得更加细腻多彩。希望对新手有所帮助。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
jQuery中验证表单提交方式及序列化表单内容的实现
Jan 06 Javascript
javascript基于prototype实现类似OOP继承的方法
Dec 16 Javascript
jquery中object对象循环遍历的方法
Dec 18 Javascript
jquery div模态窗口的简单实例
May 28 Javascript
jQuery AJAX timeout 超时问题详解
Jun 21 Javascript
JS自定义混合Mixin函数示例
Nov 26 Javascript
基于Bootstrap下拉框插件bootstrap-select使用方法详解
Aug 07 Javascript
element-ui 表格数据时间格式化的方法
Aug 24 Javascript
vue+springboot实现项目的CORS跨域请求
Sep 05 Javascript
vue-cli 使用axios的操作方法及整合axios的多种方法
Sep 12 Javascript
mpvue小程序循环动画开启暂停的实现方法
May 15 Javascript
Vue 通过公共字段,拼接两个对象数组的实例
Nov 07 Javascript
详解JavaScript中return的用法
May 08 #Javascript
如何使用angularJs
May 08 #Javascript
关于foreach循环中遇到的问题小结
May 08 #Javascript
js下载文件并修改文件名
May 08 #Javascript
JS将unicode码转中文方法
May 08 #Javascript
js实现点击切换checkbox背景图片的简单实例
May 08 #Javascript
完美解决浏览器跨域的几种方法(汇总)
May 08 #Javascript
You might like
php单元测试phpunit入门实例教程
2017/11/17 PHP
用jquery设置按钮的disabled属性的实现代码
2010/11/28 Javascript
分享一个用Mootools写的鼠标滑过进度条改变进度值的实现代码
2011/12/12 Javascript
Flexigrid在IE下不显示数据的有效处理方法
2014/09/04 Javascript
jquery获取当前元素索引值用法实例
2015/06/10 Javascript
jquery带翻页动画的电子杂志代码分享
2015/08/21 Javascript
jQuery可见性过滤选择器用法示例
2016/09/09 Javascript
javascript实现无法关闭的弹框
2016/11/27 Javascript
nodejs项目windows下开机自启动的方法
2017/11/22 NodeJs
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
深入Vue-Router路由嵌套理解
2018/08/13 Javascript
用Object.prototype.toString.call(obj)检测对象类型原因分析
2018/10/11 Javascript
在移动端使用vue-router和keep-alive的方法示例
2018/12/02 Javascript
利用Vue构造器创建Form组件的通用解决方法
2018/12/03 Javascript
react结合bootstrap实现评论功能
2020/05/30 Javascript
解决vue 给window添加和移除resize事件遇到的坑
2020/07/21 Javascript
Python标准库与第三方库详解
2014/07/22 Python
python 多线程实现检测服务器在线情况
2015/11/25 Python
Python算术运算符实例详解
2017/05/31 Python
python实现在IDLE中输入多行的方法
2018/04/19 Python
Python实现字典(dict)的迭代操作示例
2018/06/05 Python
celery4+django2定时任务的实现代码
2018/12/23 Python
PyQt5图形界面播放音乐的实例
2019/06/17 Python
Python PyInstaller库基本使用方法分析
2019/12/12 Python
使用TFRecord存取多个数据案例
2020/02/17 Python
Python 序列化和反序列化库 MarshMallow 的用法实例代码
2020/02/25 Python
Python图像处理库PIL的ImageGrab模块介绍详解
2020/02/26 Python
Mysql数据库反向生成Django里面的models指令方式
2020/05/18 Python
python3 中时间戳、时间、日期的转换和加减操作
2020/07/14 Python
HTML5中的Article和Section元素认识及使用
2013/03/22 HTML / CSS
澳大利亚领先的美容护肤品零售商之一:SkincareStore
2018/01/22 全球购物
石油大学毕业生自荐信
2014/01/28 职场文书
寒假家长评语大全
2014/04/16 职场文书
法定代表人授权委托书格式
2014/10/14 职场文书
vue项目两种方式实现竖向表格的思路分析
2021/04/28 Vue.js
腾讯云服务器部署前后分离项目之前端部署
2022/06/28 Servers