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 相关文章推荐
JavaScript 一道字符串分解的题目
Aug 03 Javascript
JavaScript高级程序设计(第3版)学习笔记5 js语句
Oct 11 Javascript
javascript的propertyIsEnumerable()方法使用介绍
Apr 09 Javascript
jQuery实现tag便签去重效果的方法
Jan 20 Javascript
JS创建对象的写法示例
Nov 04 Javascript
浅谈jquery选择器 :first与:first-child的区别
Nov 20 Javascript
AngularJS折叠菜单实现方法示例
May 18 Javascript
Javascript es7中比较实用的两个方法示例
Jul 21 Javascript
vue移动端微信授权登录插件封装的实例
Aug 28 Javascript
基于vue和react的spa进行按需加载的实现方法
Sep 29 Javascript
JavaScript中七种流行的开源机器学习框架
Oct 11 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
Oct 02 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/06/06 PHP
PHP后台实现微信小程序登录
2018/08/03 PHP
TNC vs IO BO3 第一场2.13
2021/03/10 DOTA
javascript 自动转到命名锚记
2009/01/10 Javascript
ie和firefox不兼容的解决方法集合
2009/04/28 Javascript
了解了这些才能开始发挥jQuery的威力
2013/10/10 Javascript
火狐下input焦点无法重复获取问题的解决方法
2014/06/16 Javascript
JS 滚动事件window.onscroll与position:fixed写兼容IE6的回到顶部组件
2016/10/10 Javascript
Node.js下自定义错误类型详解
2016/10/17 Javascript
最细致的vue.js基础语法 值得收藏!
2016/11/03 Javascript
jQuery validate插件功能与用法详解
2016/12/15 Javascript
Node.JS循环删除非空文件夹及子目录下的所有文件
2018/03/12 Javascript
详解node和ES6的模块导出与导入
2020/02/19 Javascript
vue+canvas实现移动端手写签名
2020/05/21 Javascript
微信小程序学习总结(二)样式、属性、模板操作分析
2020/06/04 Javascript
快速解决Vue、element-ui的resetFields()方法重置表单无效的问题
2020/08/12 Javascript
Echarts.js无法引入问题解决方案
2020/10/30 Javascript
详解vue 组件注册
2020/11/20 Vue.js
[56:45]DOTA2上海特级锦标赛D组小组赛#1 EG VS COL第一局
2016/02/28 DOTA
ssh批量登录并执行命令的python实现代码
2012/05/25 Python
基于python实现的抓取腾讯视频所有电影的爬虫
2016/04/22 Python
Python cookbook(数据结构与算法)找到最大或最小的N个元素实现方法示例
2018/02/13 Python
python中abs&amp;map&amp;reduce简介
2018/02/20 Python
python字符串常用方法
2018/06/14 Python
Django跨域请求问题的解决方法示例
2018/06/16 Python
Python SQL查询并生成json文件操作示例
2018/08/17 Python
Python使用ffmpy将amr格式的音频转化为mp3格式的例子
2019/08/08 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
pytorch cuda上tensor的定义 以及减少cpu的操作详解
2020/06/23 Python
Python爬虫定时计划任务的几种常见方法(推荐)
2021/01/15 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
Python绘制数码晶体管日期
2021/02/19 Python
兰蔻加拿大官方网站:Lancome加拿大
2016/08/05 全球购物
俄罗斯最大的隐形眼镜销售网站:Ochkov.Net
2021/02/07 全球购物
MATLAB 全景图切割及盒图显示的实现步骤
2021/05/14 Python
Django drf请求模块源码解析
2021/06/08 Python