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 Window及document对象详细整理
Jan 12 Javascript
myEvent.js javascript跨浏览器事件框架
Oct 24 Javascript
jQuery仿360导航页图标拖动排序效果代码分享
Aug 24 Javascript
JQuery中Ajax()的data参数类型实例分析
Dec 15 Javascript
浅谈js中调用函数时加不加括号的问题
Jul 28 Javascript
jQuery动态增减行的实例代码解析(推荐)
Dec 05 Javascript
JS实现touch 点击滑动轮播实例代码
Jan 19 Javascript
JavaScript ES6中的简写语法总结与使用技巧
Dec 30 Javascript
详解vue使用$http服务端收不到参数
Apr 19 Javascript
Vue项目中使用WebUploader实现文件上传的方法
Jul 21 Javascript
vue 使用v-for进行循环的实例代码详解
Feb 19 Javascript
Vue.js 中制作自定义选择组件的代码附演示demo
Feb 28 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
把从SQL中取出的数据转化成XMl格式
2006/10/09 PHP
php数组函数序列之array_keys() - 获取数组键名
2011/10/30 PHP
简要剖析PHP的Yii框架的组件化机制的基本知识
2016/03/17 PHP
Zend Framework开发入门经典教程
2016/03/23 PHP
PHP Laravel 上传图片、文件等类封装
2017/08/16 PHP
javascript tips提示框组件实现代码
2010/11/19 Javascript
html+css+js实现xp window界面及有关功能
2013/03/26 Javascript
使用indexOf等在JavaScript的数组中进行元素查找和替换
2013/09/18 Javascript
Javascript中各种trim的实现详细解析
2013/12/10 Javascript
JS获得选取checkbox整行数据的方法
2015/01/28 Javascript
详谈javascript中DOM的基本属性
2015/02/26 Javascript
JavaScript实现LI列表数据绑定的方法
2015/08/04 Javascript
jquery实现适用于门户站的导航下拉菜单效果代码
2015/08/24 Javascript
Javascript的无new构建实例详解
2016/05/15 Javascript
JavaScript提升性能的常用技巧总结【经典】
2016/06/20 Javascript
浅谈JS之tagNaem和nodeName
2016/09/13 Javascript
angularjs过滤器--filter与ng-repeat配合有奇效
2017/04/20 Javascript
js经验分享 JavaScript反调试技巧
2018/03/10 Javascript
[08:40]Navi Vs Newbee
2018/06/07 DOTA
用PyQt进行Python图形界面的程序的开发的入门指引
2015/04/14 Python
浅谈python中截取字符函数strip,lstrip,rstrip
2015/07/17 Python
Django中利用filter与simple_tag为前端自定义函数的实现方法
2017/06/15 Python
Python2和Python3之间的str处理方式导致乱码的讲解
2019/01/03 Python
Python+OpenCV感兴趣区域ROI提取方法
2019/01/10 Python
pytorch:model.train和model.eval用法及区别详解
2020/02/20 Python
CSS3 优势以及网页设计师如何使用CSS3技术
2009/07/29 HTML / CSS
韩国邮政旗下生鲜食品网上超市:epost
2016/08/27 全球购物
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
2015/02/22 面试题
感恩节红领巾广播稿
2014/02/11 职场文书
员工保密承诺书
2014/05/28 职场文书
小学生常见病防治方案
2014/06/06 职场文书
园艺专业毕业生求职信
2014/09/02 职场文书
大学生党校培训心得体会
2014/09/11 职场文书
2014年党的群众路线整改措施思想汇报
2014/10/12 职场文书
2015年导购员工作总结
2015/04/25 职场文书
Go语言并发编程 sync.Once
2021/10/16 Golang