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 选择和过滤方法代码总结
Nov 19 Javascript
7款吸引人眼球的jQuery/CSS3特效实例分享
Apr 25 Javascript
javaScript面向对象继承方法经典实现
Aug 20 Javascript
BootStrap中Datepicker控件带中文的js文件
Aug 10 Javascript
node.js Sequelize实现单实例字段或批量自增、自减
Dec 08 Javascript
Extjs gridpanel 中的checkbox(复选框)根据某行的条件不能选中的解决方法
Feb 17 Javascript
微信小程序 标签传入数据
May 08 Javascript
JS按条件 serialize() 对应标签的使用方法
Jul 24 Javascript
vue.js实现简单轮播图效果
Oct 10 Javascript
微信小程序使用canvas的画图操作示例
Jan 18 Javascript
简述pm2常用命令集合及配置文件说明
May 30 Javascript
vue中的双向数据绑定原理与常见操作技巧详解
Mar 16 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
Windows7下PHP开发环境安装配置图文方法
2010/05/20 PHP
PHP快速生成各种信息提示框的方法
2016/02/03 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
设置下载不需要倒计时cookie(倒计时代码)
2008/11/19 Javascript
javascript 密码强弱度检测万能插件
2009/02/25 Javascript
js读取本地excel文档数据的代码
2010/11/11 Javascript
JS添加删除一组文本框并对输入信息加以验证判断其正确性
2013/04/11 Javascript
js处理json以及字符串的比较等常用操作
2013/09/08 Javascript
Jquery设置attr的disabled属性控制某行显示或者隐藏
2014/09/25 Javascript
jquery幻灯片插件bxslider样式改进实例
2014/10/15 Javascript
JavaScript使用slice函数获取数组部分元素的方法
2015/04/06 Javascript
【经验总结】编写JavaScript代码时应遵循的14条规律
2016/06/20 Javascript
angular.js分页代码的实例
2016/07/27 Javascript
JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】
2018/02/06 Javascript
Vue下路由History模式打包后页面空白的解决方法
2018/06/29 Javascript
使用Phantomjs和Node完成网页的截屏快照的方法
2019/07/16 Javascript
vue watch监控对象的简单方法示例
2021/01/07 Vue.js
在Python中利用Into包整洁地进行数据迁移的教程
2015/03/30 Python
Python的Tornado框架异步编程入门实例
2015/04/24 Python
Python基础入门之seed()方法的使用
2015/05/15 Python
python 迭代器和iter()函数详解及实例
2017/03/21 Python
python实现m3u8格式转换为mp4视频格式
2018/02/28 Python
Python3中的列表生成式、生成器与迭代器实例详解
2018/06/11 Python
Python3实现汉语转换为汉语拼音
2019/07/08 Python
使用py-spy解决scrapy卡死的问题方法
2020/09/29 Python
matplotlib更改窗口图标的方法示例
2021/02/03 Python
两种CSS3伪类选择器详细介绍
2013/12/24 HTML / CSS
DVF官方网站:美国时装界尊尚品牌
2017/08/29 全球购物
可持续木材、生态和铝制太阳镜:Proof Eyewear
2019/07/24 全球购物
Java如何读取CLOB字段
2013/10/10 面试题
社区平安建设汇报材料
2014/08/14 职场文书
2015年党员自评材料
2014/12/17 职场文书
国家助学金感谢信
2015/01/21 职场文书
2015年组织部工作总结
2015/04/03 职场文书
使用springMVC所需要的pom配置
2021/09/15 Java/Android
Java中Dijkstra(迪杰斯特拉)算法
2022/05/20 Java/Android