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 相关文章推荐
js获取div高度的代码
Aug 09 Javascript
JS实现可改变列宽的table实例
Jul 02 Javascript
JavaScript整除运算函数ceil和floor的区别分析
Apr 14 Javascript
七夕情人节丘比特射箭小游戏
Aug 20 Javascript
javascript省市级联功能实现方法实例详解
Oct 20 Javascript
AngularJs  Creating Services详解及示例代码
Sep 02 Javascript
老生常谈jquery中detach()和remove()的区别
Mar 02 Javascript
node.js+jQuery实现用户登录注册AJAX交互
Apr 28 jQuery
JavaScript解析任意形式的json树型结构展示
Jul 23 Javascript
vue技术分享之你可能不知道的7个秘密
Apr 09 Javascript
如何在Node和浏览器控制台中打印彩色文字
Jan 09 Javascript
JQuery表单元素取值赋值方法总结
May 12 jQuery
详解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下判断网址是否有效的代码
2011/10/08 PHP
php实现12306火车票余票查询和价格查询(12306火车票查询)
2014/01/14 PHP
PHP标准类(stdclass)用法示例
2016/09/28 PHP
laravel5.2实现区分前后台用户登录的方法
2017/01/11 PHP
php数据库的增删改查 php与javascript之间的交互
2017/08/31 PHP
javascript 当前日期加(天、周、月、年)
2009/08/09 Javascript
Javascript判断对象是否相等实现代码
2013/03/18 Javascript
基于jquery实现一张图片点击鼠标放大再点缩小
2013/09/29 Javascript
创建、调用JavaScript对象的方法集锦
2014/12/24 Javascript
JavaScript中join()方法的使用简介
2015/06/09 Javascript
JS实现的打字机效果完整实例
2016/06/20 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
2017/04/27 Javascript
react-router4 配合webpack require.ensure 实现异步加载的示例
2018/01/18 Javascript
如何理解Vue的v-model指令的使用方法
2018/07/19 Javascript
vue使用v-if v-show页面闪烁,div闪现的解决方法
2018/10/12 Javascript
vue改变循环遍历后的数据实例
2019/11/07 Javascript
jquery实现两个div中的元素相互拖动的方法分析
2020/04/05 jQuery
[00:30]明星选手化身超级英雄!2018DOTA2亚洲邀请赛全明星赛来临!
2018/04/06 DOTA
[36:16]完美世界DOTA2联赛PWL S3 access vs Rebirth 第一场 12.19
2020/12/24 DOTA
详解Python的Flask框架中生成SECRET_KEY密钥的方法
2016/06/07 Python
python实战串口助手_解决8串口多个发送的问题
2019/06/12 Python
django框架实现一次性上传多个文件功能示例【批量上传】
2019/06/19 Python
Python搭建Spark分布式集群环境
2019/07/05 Python
python redis连接 有序集合去重的代码
2019/08/04 Python
Python IDE Pycharm中的快捷键列表用法
2019/08/08 Python
手动安装python3.6的操作过程详解
2020/01/13 Python
意大利一家专营包包和配饰的网上商店:Borse Last Minute
2019/08/26 全球购物
中国旅游网站:途牛旅游网
2019/09/29 全球购物
大四学年自我鉴定
2013/11/13 职场文书
父亲婚礼答谢词
2015/01/04 职场文书
初中教师个人工作总结
2015/02/10 职场文书
企业办公室主任岗位职责
2015/04/01 职场文书
民事二审代理词
2015/05/25 职场文书
文化苦旅读书笔记
2015/06/29 职场文书
哈姆雷特读书笔记
2015/06/29 职场文书
小型企业的绩效考核制度模板
2019/11/21 职场文书