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 相关文章推荐
基于jquery的手风琴图片展示效果实现方法
Dec 16 Javascript
jQuery采用连缀写法实现的折叠菜单效果
Sep 18 Javascript
Bootstrap 粘页脚效果
Mar 28 Javascript
vue深入解析之render function code详解
Jul 18 Javascript
详解webpack + react + react-router 如何实现懒加载
Nov 20 Javascript
JS中数据结构之栈
Jan 01 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
Jan 18 Javascript
vue项目首屏加载时间优化实战
Apr 23 Javascript
微信小程序中使用echarts的实现方法
Apr 24 Javascript
vue router 传参获取不到的解决方式
Nov 13 Javascript
如何在微信小程序中存setStorage
Dec 13 Javascript
antd design table更改某行数据的样式操作
Oct 31 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
Smarty Foreach 使用说明
2010/03/23 PHP
ThinkPHP标签制作教程
2014/07/10 PHP
PHP获取当前所在目录位置的方法
2014/11/26 PHP
很多人都是用下面的js刷新站IP和PV
2008/09/05 Javascript
javascript算法学习(直接插入排序)
2011/04/12 Javascript
javaScript 删除字符串空格多种方法小结
2012/10/24 Javascript
事件冒泡是什么如何用jquery阻止事件冒泡
2013/03/20 Javascript
用js来获取上传的文件名纯粹是为了美化而用
2013/10/23 Javascript
js给onclick赋值传参数的两种方法
2013/11/25 Javascript
Javascript中的作用域和上下文深入理解
2015/07/03 Javascript
基于jquery实现复选框全选,反选,全不选等功能
2015/10/16 Javascript
JavaScript函数的调用以及参数传递
2015/10/21 Javascript
jQuery Easyui datagrid editor为combobox时指定数据源实例
2016/12/19 Javascript
AngularJS自定义指令之复制指令实现方法
2017/05/18 Javascript
对Angular中单向数据流的深入理解
2018/03/31 Javascript
微信小程序发送短信验证码完整实例
2019/01/07 Javascript
Nodejs异步流程框架async的方法
2019/06/07 NodeJs
微信小程序8种数据通信的方式小结
2020/02/03 Javascript
vue created钩子函数与mounted钩子函数的用法区别
2020/11/05 Javascript
python下载图片实现方法(超简单)
2017/07/21 Python
Python基于matplotlib绘制栈式直方图的方法示例
2017/08/09 Python
浅谈Python对内存的使用(深浅拷贝)
2018/01/17 Python
Python编程快速上手——PDF文件操作案例分析
2020/02/28 Python
Python批量删除mysql中千万级大量数据的脚本分享
2020/12/03 Python
input file上传文件样式支持html5的浏览器解决方案
2012/11/14 HTML / CSS
Stefania Mode英国:奢华设计师和时尚服装
2017/10/23 全球购物
怎样声明接口
2014/09/19 面试题
运动员获奖感言
2014/08/15 职场文书
小学感恩节活动策划方案
2014/10/06 职场文书
贪污检举信范文
2015/03/02 职场文书
2015年新教师工作总结
2015/04/28 职场文书
2015年董事长秘书工作总结
2015/07/23 职场文书
青年干部培训班学习心得体会
2016/01/06 职场文书
CocosCreator如何实现划过的位置显示纹理
2021/04/14 Javascript
Java并发编程之原子性-Atomic的使用
2022/03/16 Java/Android
分享node.js实现简单登录注册的具体代码
2022/04/26 NodeJs