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 匿名调用实现代码
Jun 19 Javascript
jQuery焦点图切换简易插件制作过程全纪录
Aug 27 Javascript
angularjs学习笔记之完整的项目结构
Sep 26 Javascript
JQuery实现简单的服务器轮询效果实例
Mar 31 Javascript
浅谈JS继承_借用构造函数 &amp; 组合式继承
Aug 16 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
Sep 21 Javascript
jQuery实现拖动效果的实例代码
Jun 25 jQuery
浅谈vue同一页面中拥有两个表单时,的验证问题
Sep 18 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
Apr 26 Javascript
Vue请求java服务端并返回数据代码实例
Nov 28 Javascript
Layer UI表格列日期格式化及取消自动填充日期的实现方法
May 10 Javascript
使用JavaScript获取Django模板指定键值数据
May 27 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语言构造器介绍
2013/07/08 PHP
THINKPHP2.0到3.0有哪些改进之处
2015/01/04 PHP
静态html文件执行php语句的方法(推荐)
2016/11/21 PHP
php防止sql注入的方法详解
2017/02/20 PHP
PHP实现蛇形矩阵,回环矩阵及数字螺旋矩阵的方法分析
2017/05/29 PHP
PHP实现git部署的方法教程
2017/12/19 PHP
javascript脚本编程解决考试分数统计问题
2008/10/18 Javascript
前台js调用后台方法示例
2013/12/02 Javascript
禁用Enter键表单自动提交实现代码
2014/05/22 Javascript
完美兼容各大浏览器获取HTTP_REFERER方法总结
2014/06/24 Javascript
jQuery中复合属性选择器用法实例
2014/12/31 Javascript
原生JavaScript实现滚动条效果
2020/03/24 Javascript
基于javascript实现样式清新图片轮播特效
2016/03/30 Javascript
JS+CSS3制作炫酷的弹窗效果
2016/11/08 Javascript
Vue 2.x教程之基础API
2017/03/06 Javascript
ionic环境配置及问题详解
2017/06/27 Javascript
JS+canvas动态绘制饼图的方法示例
2017/09/12 Javascript
vue路由跳转时判断用户是否登录功能的实现
2017/10/26 Javascript
简单介绍react redux的中间件的使用
2018/04/06 Javascript
vee-validate vue 2.0自定义表单验证的实例
2018/08/28 Javascript
图文讲解vue的v-if使用方法
2019/02/11 Javascript
seajs和requirejs模块化简单案例分析
2019/08/26 Javascript
vue element-ui实现input输入框金额数字添加千分位
2019/12/29 Javascript
python判断端口是否打开的实现代码
2013/02/10 Python
Python实现的用户登录系统功能示例
2018/02/05 Python
python判断计算机是否有网络连接的实例
2018/12/15 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
Pytorch: 自定义网络层实例
2020/01/07 Python
浅谈在JupyterNotebook下导入自己的模块的问题
2020/04/16 Python
Python新手学习raise用法
2020/06/03 Python
css3实现背景模糊的三种方式(小结)
2020/05/15 HTML / CSS
房地产推广策划方案
2014/05/19 职场文书
学校搬迁方案
2014/06/15 职场文书
2014教师党员自我评议总结
2014/09/19 职场文书
工商局局长个人对照检查材料思想汇报
2014/09/23 职场文书
初中政治教师教学反思
2016/02/23 职场文书