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 相关文章推荐
一个不错的应用,用于提交获取文章内容,不推荐用
Mar 03 Javascript
Dom在ajax技术中的作用说明
Oct 25 Javascript
javascript运动详解
Jul 06 Javascript
jQuery实现带渐显效果的人物多级关系图代码
Oct 16 Javascript
jquery仿ps颜色拾取功能
Mar 08 Javascript
Vue.Js中的$watch()方法总结
Mar 23 Javascript
使用canvas及js简单生成验证码方法
Apr 02 Javascript
详解vue2.0的Element UI的表格table列时间戳格式化
Jun 13 Javascript
vue教程之toast弹框全局调用示例详解
Aug 24 Javascript
Parcel 打包示例(React HelloWorld)
Jan 16 Javascript
vue 2.0 购物车小球抛物线的示例代码
Feb 01 Javascript
JavaScript获取某一天所在的星期
Sep 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
无线电波是什么?它是怎样传输的?
2021/03/01 无线电
谈谈PHP语法(2)
2006/10/09 PHP
php 高性能书写
2010/12/11 PHP
让Nginx支持ThinkPHP的URL重写和PATHINFO的方法分享
2011/08/08 PHP
解析php中如何调用用户自定义函数
2013/08/06 PHP
wordpress自定义url参数实现路由功能的代码示例
2013/11/28 PHP
php实现高效获取图片尺寸的方法
2014/12/12 PHP
php文件下载处理方法分析
2015/04/22 PHP
PHP生成各种常见验证码和Ajax验证过程
2016/01/10 PHP
PHP批量删除jQuery操作
2017/07/23 PHP
jquery $.each 和for怎么跳出循环终止本次循环
2013/09/27 Javascript
javascript动态生成树形菜单的方法
2015/11/14 Javascript
AngularJs解决跨域问题案例详解(简单方法)
2016/05/19 Javascript
最棒的Angular2表格控件
2016/08/10 Javascript
onmouseover事件和onmouseout事件全面理解
2016/08/15 Javascript
jQuery图片切换动画效果
2017/02/28 Javascript
vue监听滚动事件实现滚动监听
2017/04/11 Javascript
javascript trie前缀树的示例
2018/01/29 Javascript
JS 自执行函数原理及用法
2019/08/05 Javascript
JavaScript异步操作的几种常见处理方法实例总结
2020/05/11 Javascript
javascript实现多边形碰撞检测
2020/10/24 Javascript
python del()函数用法
2013/03/24 Python
python检测远程udp端口是否打开的方法
2015/03/14 Python
将Python的Django框架与认证系统整合的方法
2015/07/24 Python
Python3访问并下载网页内容的方法
2015/07/28 Python
python脚本实现xls(xlsx)转成csv
2016/04/10 Python
Python数据结构与算法之常见的分配排序法示例【桶排序与基数排序】
2017/12/15 Python
基于python指定包的安装路径方法
2018/10/27 Python
Python将字符串常量转化为变量方法总结
2019/03/17 Python
Django 静态文件配置过程详解
2019/07/23 Python
numpy:找到指定元素的索引示例
2019/11/26 Python
苹果香港官方商城:Apple香港
2016/09/14 全球购物
Theory美国官网:后现代都市风时装品牌
2018/05/09 全球购物
北京颐和园导游词
2015/01/30 职场文书
司机岗位职责范本
2015/04/10 职场文书
淘宝文案策划岗位职责
2015/04/14 职场文书