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增删元素的代码
Feb 14 Javascript
JavaScript中提前声明变量或函数例子
Nov 12 Javascript
jquery checkbox 勾选的bug问题解决方案与分析
Nov 13 Javascript
运行Node.js的IIS扩展iisnode安装配置笔记
Mar 02 Javascript
浅谈Sizzle的“编译原理”
Apr 14 Javascript
javascript多行字符串的简单实现方式
May 04 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
May 07 Javascript
JavaScript伪数组用法实例分析
Dec 22 Javascript
JavaScript寄生组合式继承实例详解
Jan 06 Javascript
深入解析vue 源码目录及构建过程分析
Apr 24 Javascript
实现vuex与组件data之间的数据同步更新方式
Nov 12 Javascript
在Vue.js中使用TypeScript的方法
Mar 19 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 sprintf()函数让你的sql操作更安全
2008/07/23 PHP
php 判断访客是否为搜索引擎蜘蛛的函数代码
2011/07/29 PHP
一个漂亮的php验证码类(分享)
2013/08/06 PHP
PHP实现搜索相似图片
2015/09/22 PHP
thinkPHP5框架设置404、403等http状态页面的方法
2018/06/05 PHP
ThinkPHP框架下微信支付功能总结踩坑笔记
2019/04/10 PHP
js获取当前select 元素值的代码
2010/04/19 Javascript
JavaScript高级程序设计 阅读笔记(七) ECMAScript中的语句
2012/02/27 Javascript
jquery scrollTop方法根据滚动像素显示隐藏顶部导航条
2013/05/27 Javascript
jquery cookie的用法总结
2013/11/18 Javascript
jQuery中bind,live,delegate与one方法的用法及区别解析
2013/12/30 Javascript
JS+CSS实现的蓝色table选项卡效果
2015/10/08 Javascript
JS中Eval解析JSON字符串的一个小问题
2016/02/21 Javascript
Javascript HTML5 Canvas实现的一个画板
2020/04/12 Javascript
基于javascript实现图片滑动效果
2016/05/07 Javascript
基于JavaScript实现新增内容滚动播放效果附完整代码
2017/08/24 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
vue实现购物车小案例
2019/09/27 Javascript
Vue通过getAction的finally来最大程度避免影响主数据呈现问题
2020/04/24 Javascript
微信小程序中使用 async/await的方法实例分析
2020/05/06 Javascript
[03:40]2014DOTA2国际邀请赛 B神专访:躲箭真的很难
2014/07/13 DOTA
详解Python的Django框架中Manager方法的使用
2015/07/21 Python
详解python之简单主机批量管理工具
2017/01/27 Python
Tensorflow实现AlexNet卷积神经网络及运算时间评测
2018/05/24 Python
Python通过正则库爬取淘宝商品信息代码实例
2020/03/02 Python
Web时代变迁及html5与html4的区别
2016/01/06 HTML / CSS
html5表单及新增的改良元素详解
2016/06/07 HTML / CSS
澳大利亚领先的皮肤诊所:Skin Matrix(抗衰老、痤疮专家、药妆护肤)
2018/05/20 全球购物
The Beach People美国:澳洲海滨奢华品牌
2018/07/05 全球购物
商场中秋节广播稿
2014/01/17 职场文书
大学生两会精神学习心得体会
2014/03/10 职场文书
护理专业毕业生自荐书
2014/05/24 职场文书
2015入党个人自传范文
2015/06/26 职场文书
小学大队委竞选口号
2015/12/25 职场文书
Redis如何实现分布式锁
2021/08/23 Redis
Python 操作pdf pdfplumber读取PDF写入Exce
2022/08/14 Python