canvas大雪纷飞

前言:正好业务触及到canvas,看完api顺手写个雪花效果,因为之前看到过很多次这个,主要看思路,想象力好的可以慢慢去创作属于自己的canvas效果

思路:

  • 利用画圆arc()和环形渐变色createRadialGradient()画一个雪花的模型(想要更好看的模型可以用图片代替)
  1. var grd = this.canvas.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.r);
  2. grd.addColorStop(0, "rgba(255,255,255,1)");
  3. grd.addColorStop(1, "rgba(255,255,255,0.2)");
  4. this.canvas.fillStyle = grd;
  5. this.canvas.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
  6. this.canvas.fill();

效果图

  • 如何让canvas画布上的点移动

动画其实就是一帧一帧的画面的组合,在一定时间内把画面从第一帧切换到第二帧到第n帧这个过程就是动画
弄懂这个道理,让雪花动起来就很简单了,重绘。
改变雪花的x,y坐标,在短时间内重绘一次,然后不断重复此过程,为了照顾浏览器爸爸的感受,x,y超出画布边界的时候把雪花清除掉。

  1. setInterval(() => {
  2. arr[0].canvas.clearRect(0, 0, maxW, maxH);
  3. for(var i = 0; i < arr.length; i++) {
  4. if(arr[i].y >= maxH){
  5. //清除超出下边界的雪花
  6. continue;
  7. }
  8. arr[i].play();
  9. }
  10. }, 30);
  11. play: function() {
  12. this.x += this.speedX;
  13. this.y += this.speedY;
  14. if(this.x < this.r) {
  15. this.speedX = Math.abs(this.speedX);
  16. }
  17. if(this.y < this.r) {
  18. this.speedY = Math.abs(this.speedY);
  19. }
  20. this.canvas.beginPath();
  21. var grd = this.canvas.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.r);
  22. grd.addColorStop(0, "rgba(255,255,255,1)");
  23. grd.addColorStop(1, "rgba(255,255,255,0.2)");
  24. this.canvas.fillStyle = grd;
  25. this.canvas.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
  26. this.canvas.fill();
  27. }
  • 最后一步就是创建一个个雪花实例去执行动画了
  1. var snow = function() {
  2. this.x = this.rand(maxW);
  3. this.y = 0;
  4. this.r = this.rand(10);
  5. this.speedX = this.getRanNum(-5, 5);
  6. this.speedY = this.getRanNum(10, 20);
  7. this.width = 0;
  8. this.height = 0;
  9. this.canvas = {};
  10. this.init();
  11. }
  12. var arr = [];
  13. setInterval(() => {
  14. for(let i = 0; i < 10; i++) {
  15. arr.push(new snow());
  16. }
  17. }, 30);

效果预览

完整代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style type="text/css">
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. body {
  12. background-color: '#fff';
  13. }
  14. canvas {
  15. background-color: rgba(0, 0, 0, 1);
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <canvas id="canvas" width="1000px" height="500px"></canvas>
  21. <script type="text/javascript">
  22. var myCanvas = document.getElementById('canvas')
  23. var ctx = myCanvas.getContext('2d');
  24. var clientW = window.innerWidth;
  25. var clientH = window.innerHeight;
  26. myCanvas.width = clientW;
  27. myCanvas.height = clientH;
  28. var maxW = clientW;
  29. var maxH = clientH;
  30. //雪花实例构造函数
  31. var snow = function() {
  32. this.r = this.rand(10);
  33. this.x = this.rand(maxW);
  34. this.y = 0;
  35. this.speedX = this.getRanNum(-5, 5);
  36. this.speedY = this.getRanNum(10, 20);
  37. this.width = 0;
  38. this.height = 0;
  39. this.canvas = {};
  40. this.init();
  41. }
  42. snow.prototype = {
  43. //初始化
  44. init: function() {
  45. var snow = document.getElementById('canvas');
  46. this.canvas = snow.getContext('2d');
  47. this.width = snow.width;
  48. this.height = snow.height;
  49. },
  50. //获取0-num之间的随机数
  51. rand: function(num) {
  52. return Math.floor(Math.random() * num + 1);
  53. },
  54. //获取n-m之间的随机数
  55. getRanNum: function (n, m) {
  56. return Math.floor(Math.random() * (m - n) + n);
  57. },
  58. //雪花移动
  59. play: function() {
  60. //改变坐标位置 连续重绘形成动画效果
  61. this.x += this.speedX;
  62. this.y += this.speedY;
  63. this.canvas.beginPath();
  64. //定义雪花UI 渐变色+圆
  65. var snowColor = this.canvas.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.r);
  66. snowColor.addColorStop(0, "rgba(255,255,255,1)");
  67. snowColor.addColorStop(1, "rgba(255,255,255,0.2)");
  68. this.canvas.fillStyle = snowColor;
  69. this.canvas.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
  70. this.canvas.fill();
  71. }
  72. };
  73. var arr = [];
  74. //生成新雪花的速度 每30ms生成10个
  75. setInterval(() => {
  76. for(let i = 0; i < 10; i++) {
  77. arr.push(new snow());
  78. }
  79. }, 30);
  80. //雪花重绘(即帧,多帧即移动动画) 30ms重绘一次
  81. setInterval(() => {
  82. arr[0].canvas.clearRect(0, 0, maxW, maxH);
  83. for(let i = 0; i < arr.length; i++) {
  84. if(arr[i].y >= maxH){
  85. //清除超出下边界的雪花
  86. arr.splice(i,1);
  87. continue;
  88. }
  89. arr[i].play();
  90. }
  91. }, 30);
  92. </script>
  93. </body>
  94. </html>

最后,每几个canvas的方法组合一下做个小效果,慢慢的就可以做大型炫酷效果了,当然,炫酷效果离不开一些常用或生僻的数学知识,各类算法,方法,相关插件(我说的插件是用来计算一些东西或者图形之类的,不是用插件画canvas)作为铺垫
敲黑板,希望路过的大神能介绍一些canvas进阶需要学习的一些知识点,小弟不胜感激~

版权所有,转载请注明出处~

玩别人玩剩下的:canvas大雪纷飞的更多相关文章

  1. 为什么说程序员都应该玩一玩GitHub

    既熟悉又陌生的GitHub 关于GitHub,相信每一个程序员都再熟悉不过了.它为开发者提供Git仓库的托管服务,是全世界最大的代码集中地,被戏称为“全球最大同性交友网站”. 但是对于很大一部分程序员 ...

  2. 玩一玩nodejs--一个简单的在线实时填表应用

    学习nodejs三天,入了个门,感觉他和jsp.php还是存在较大的差别.本文首先复习这些天学的一些知识点,然后谈一下如何一步一步到做一个在线实时填表的小应用,进一步巩固一下这些个知识点.这里先简单介 ...

  3. 一起玩转玩转LiteOS组件:TinyFrame

    摘要:TinyFrame是一个简单的用于解析串口(如 UART.telnet.套接字等)通信数据帧的库. 本文分享自华为云社区<LiteOS组件尝鲜-玩转TinyFrame>,作者:Lio ...

  4. 玩一玩基于Token的 自定义身份认证+权限管理

    使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录.大概的流程是这样的: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 Toke ...

  5. 无语啊,sublime给我弄乱玩,玩坏了,而且安装插件也安装不了

    国内的什么插件地址都TMMD失效了,没办法,只能翻"强"到外面找了,而且找了很多也用不了,所以收藏一个为了预防以后不行有补救的方法: 百度的99%都不行,不是报这个错就是那个错,可 ...

  6. 想挑战AlphaGO吗?先和PostgreSQL玩一玩?? PostgreSQL与人工智能(AI)

    1月4日晚,随着古力认输,Master对人类顶尖高手的战绩停留在60胜0负1和,而令人尴尬的是这唯一一场和棋还是因为棋手掉线系统自动判和,并不是棋盘上的局势真的势均力敌了.包括聂卫平.柯洁.朴廷桓.井 ...

  7. js 玩一玩

    闲着没事学了学js,做了一个下页面玩玩. 下面是html代码: <!DOCTYPE html><html> <head> <meta charset=&quo ...

  8. .NET Core 玩一玩 Ocelot API网关

    .net 这几年国内确实不好过. 很多都选择转行.不过.net Core跨平台 开源之后 .社区的生态在慢慢建立.往好的趋势发展. 对于坚守在.NET战线的开发者来说 是个挺不错的消息.  特别是微软 ...

  9. 玩一玩MEAN

    参考的书如下: Manning.Getting.MEAN.with.Mongo.Express.Angular.and.Node. 开始再次了解.

随机推荐

  1. k8s全方位监控中-常用rules配置

    [root@VM_0_48_centos prometheus]# cat alertmanager-configmap.yaml apiVersion: v1 kind: ConfigMap met ...

  2. Oracle数据库工程实训笔记

    Oracle的配置 一.配置监听和本地服务名配置 分别是 E:\oraclexe\app\oracle\product\11.2.0\server\network\ADMIN 下的这两个文件: 监听配 ...

  3. JZ-068-打印从 1 到最大的 n 位数

    打印从 1 到最大的 n 位数 题目描述 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数.比如输入 3,则打印出 1.2.3 一直到最大的 3 位数即 999. 题目链接: 打印从 1 到 ...

  4. WPF-GridView设置列宽按比例分配

    将ListView包裹在一个父Grid中 写一个与ListView平行的Grid,设置该Grid的列数与ListView中GridView的列数相同,将该Grid各列设置列宽按比例分配 将ListVi ...

  5. 面试题--Nginx

    Nginx面试题 整理自网络,侵权删 1.请解释一下什么是Nginx? Nginx是一个web服务器和反向代理服务器,用于http.https.smtp.pop3和IMAP协议 2.请列举Nginx的 ...

  6. C/C++语言读取SEGY文件笔记(一)

    SEGY IO 推荐采用的IDE为Visual studio(VS),本文档将介绍SEGY文件的读取与写入过程,即SEGY文件的复制. 因此,新建头文件ReadSeismic.h与C++文件ReadS ...

  7. 微信网页JSDK接口-wx.chooseImage问题

    wx.chooseImage({count: 1, // 默认9sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有sourceTy ...

  8. vite2 打包的时候vendor-xxx.js文件过大的解决方法

    vite2是一个非常好用的工具,只是随着代码的增多,打包的时候 vendor-xxxxxx.js 文件也越来越大,这就郁闷了. 打包时遇到警告 输出文件名字/static/vendor.9b5698e ...

  9. 论如何在使用RedisStandaloneConfiguration时让JedisConnectionFactory用上JedisPoolConfig

    前言 公司项目上线后经常运行一两天后就会出现延时.无响应的情况,当时第一反应觉得可能是某些业务优化不行,检查业务也没发现有什么问题,前前后后倒是修了两三个BUG,本以为没啥事儿了,但也就好了两天,很奇 ...

  10. centos7升级openssh8.7&openssl1.1.1l脚本

    脚本下载地址或首页联系本人获取 https://files.cnblogs.com/files/blogs/705493/update_ssh.sh 需搭配openssh8.7和openssl1.1. ...