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 相关文章推荐
Javascript 汉字字节判断
Aug 01 Javascript
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
Jul 17 Javascript
js读写json文件实例代码
Oct 21 Javascript
jquery动态添加删除(tr/td)
Feb 09 Javascript
jQuery模拟黑客帝国矩阵效果实例
Jun 28 Javascript
基于JS实现简单的样式切换效果代码
Sep 04 Javascript
延时加载JavaScript代码提高速度
Dec 27 Javascript
js表单序列化判断空值的实例
Sep 22 Javascript
JS中的回调函数实例浅析
Mar 21 Javascript
如何解决React官方脚手架不支持Less的问题(小结)
Sep 12 Javascript
详解微信小程序-canvas绘制文字实现自动换行
Apr 26 Javascript
Angular 多级路由实现登录页面跳转(小白教程)
Nov 19 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
thinkPHP5.0框架验证码调用及点击图片刷新简单实现方法
2018/09/07 PHP
Thinkphp5.0 框架使用模型Model添加、更新、删除数据操作详解
2019/10/11 PHP
字段太多jquey快速清空表单内容方法
2014/08/21 Javascript
JavaScript+CSS实现的可折叠二级菜单实例
2016/02/29 Javascript
JavaScript修改作用域外变量的方法
2016/03/25 Javascript
js创建jsonArray传输至后台及后台全面解析
2016/04/11 Javascript
Javascript基础教程之比较null和undefined值
2016/05/16 Javascript
Jquery和JS获取ul中li标签的实现方法
2016/06/02 Javascript
纯JS焦点图特效实例(可一个页面多用)
2016/12/07 Javascript
20行js代码实现的贪吃蛇小游戏
2017/06/20 Javascript
jquery一键控制checkbox全选、反选或全不选
2017/10/16 jQuery
jQuery 实现倒计时天,时,分,秒功能
2018/07/31 jQuery
详解angular部署到iis出现404解决方案
2018/08/14 Javascript
详解element-ui中form验证杂记
2019/03/04 Javascript
通过Nodejs搭建网站简单实现注册登录流程
2019/06/14 NodeJs
Vue 中获取当前时间并实时刷新的实现代码
2020/05/12 Javascript
[00:34]TI7不朽珍藏III——纯金地穴编织者饰品展示
2017/07/15 DOTA
浅谈python可视化包Bokeh
2018/02/07 Python
numpy中的delete删除数组整行和整列的实例
2018/05/09 Python
python处理自动化任务之同时批量修改word里面的内容的方法
2019/08/23 Python
python [:3] 实现提取数组中的数
2019/11/27 Python
Python Sqlalchemy如何实现select for update
2020/10/12 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
2020/11/27 Python
boostrap modal 闪现问题的解决方法
2020/09/01 HTML / CSS
美国百货齐全的精品网站,提供美式风格的产品:Overstock.com
2016/07/22 全球购物
Emporio Armani腕表天猫官方旗舰店:乔治·阿玛尼为年轻人设计的副线品牌
2017/07/02 全球购物
材料成型专业个人求职信范文
2013/09/25 职场文书
同学聚会老师邀请函
2014/01/28 职场文书
学生手册评语
2014/05/05 职场文书
购房个人委托书范本
2014/10/11 职场文书
2014年管理工作总结
2014/11/22 职场文书
户外活动总结
2015/02/04 职场文书
2015年电厂工作总结范文
2015/05/13 职场文书
2015年支教教师工作总结
2015/07/22 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python
JavaScript高级程序设计之基本引用类型
2021/11/17 Javascript