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 相关文章推荐
10个基于jQuery或JavaScript的WYSIWYG 编辑器整理
May 06 Javascript
JavaScript去掉数组中的重复元素
Jan 13 Javascript
jQuery中mouseover事件用法实例
Dec 26 Javascript
JS去除空格和换行的正则表达式(推荐)
Jun 14 Javascript
require简单实现单页应用程序(SPA)
Jul 12 Javascript
浅谈Vue的加载顺序探讨
Oct 25 Javascript
JS中移除非数字最多保留一位小数
May 09 Javascript
vue使用技巧及vue项目中遇到的问题
Jun 04 Javascript
详解Vue.js iview实现树形权限表(可扩展表)
Sep 30 Javascript
ES6的Fetch异步请求的实现方法
Dec 07 Javascript
详解Vue、element-ui、axios实现省市区三级联动
May 07 Javascript
Vue路由管理器Vue-router的使用方法详解
Feb 05 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判断变量的函数
2012/04/24 PHP
php基于双向循环队列实现历史记录的前进后退等功能
2015/08/08 PHP
基于PHP实现假装商品限时抢购繁忙的效果
2015/10/16 PHP
thinkPHP分组后模板无法加载问题解决方法
2016/07/12 PHP
获取Javscript执行函数名称的方法
2006/12/22 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
2013/11/14 Javascript
JavaScript实现仿淘宝商品购买数量的增减效果
2016/01/22 Javascript
jQuery操作iframe中js函数的方法小结
2016/07/06 Javascript
非常实用的vue导航钩子
2017/03/20 Javascript
node实现基于token的身份验证
2018/04/09 Javascript
vue使用自定义icon图标的方法
2018/05/14 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
2018/05/30 Javascript
打通前后端构建一个Vue+Express的开发环境
2018/07/17 Javascript
解决vue中修改了数据但视图无法更新的情况
2018/08/27 Javascript
ES6 Generator函数的应用实例分析
2019/06/26 Javascript
package.json各个属性说明详解
2020/03/11 Javascript
JS实现canvas简单小画板功能
2020/06/23 Javascript
python opencv实现切变换 不裁减图片
2018/07/26 Python
Python常见数字运算操作实例小结
2019/03/22 Python
python3模拟实现xshell远程执行liunx命令的方法
2019/07/12 Python
在Django中实现添加user到group并查看
2019/11/18 Python
python列表推导式入门学习解析
2019/12/02 Python
python在linux环境下安装skimage的示例代码
2020/10/14 Python
Python基于tkinter canvas实现图片裁剪功能
2020/11/05 Python
用Python实现定时备份Mongodb数据并上传到FTP服务器
2021/01/27 Python
英国网上花店:Bunches
2016/11/29 全球购物
翻新二手苹果产品的网络领导者:Mac of all Trades
2017/12/19 全球购物
公务员培训自我鉴定
2013/09/19 职场文书
网游商务专员求职信
2013/10/15 职场文书
物流专业大学生求职信范文
2013/10/28 职场文书
30岁生日感言
2014/01/25 职场文书
一分钟演讲稿
2014/04/30 职场文书
团日活动总结书
2014/05/08 职场文书
2014年乡镇团委工作总结
2014/12/18 职场文书
CSS 伪元素::marker详解
2021/06/26 HTML / CSS
Python可变集合和不可变集合的构造方法大全
2021/12/06 Python