[js高手之路]html5canvas动画教程-下雪效果

ghostwu      2022-02-14     679

关键词:

利用canvas,实现一个下雪的效果,我们先预览下效果:

 

 

我们先分析下这个效果:

1,随机产生雪花

2,雪花的产生不是同时产生,而是有先后顺序的

3,雪花怎么表示

4,怎么源源不断的下雪

5,雪花有大有小

搞清楚上面几个问题之后,这个效果基本上就实现了,

首先,由于这个是全屏效果,我采用动态创建canvas,把整个浏览器的宽与高赋值给canvas

 1         var Canvas = function (w, h) {
 2                 this.width = w;
 3                 this.height = h;
 4             }
 5             Canvas.prototype = {
 6                 init: function () {
 7                     var oC = document.createElement("canvas");
 8                     oC.setAttribute('width', this.width);
 9                     oC.setAttribute('height', this.height);
10                     oC.setAttribute('id', 'canvas');
11                     oC.style.backgroundColor = '#000';
12                     document.body.appendChild(oC);
13                 }
14             }
15             var curWinWidth = window.innerWidth,
16                 curWinHeight = window.innerHeight;
17             var oCanvas = new Canvas(curWinWidth, curWinHeight);
18             oCanvas.init();

调用oCanvas对象的init方法之后,就会在body的最后面追加一个canvas,id为canvas,宽、高与浏览器的宽、高相同,背景为黑色,晚上下雪的效果

接下来,有了舞台,演员该上场了,怎么产生雪花呢?这里把下雪相关的操作,封装成一个类,他的基本结构如下:

var Snow = function(){}

Snow.prototype = {

  init : function(){},

  draw : function( cxt ) {},

  update : function(){}

}

这个类一共有三个方法( init, draw, update ).

init:初始化雪花的位置( x, y 坐标 )、速度、半径( 雪花的大小,在这里我们把雪花用半径不同的圆表示 )

            function random(min, max) {
                return Math.random() * (max - min) + min;
            }

            init: function () {
                    this.x = random(0, width);
                    this.y = 0;
                    this.r = random(1, 5);
                    this.vy = random(3, 5);
                }

那么init 加上 这个random函数 就可以完成雪花的初始化

1,雪花出来的时候,一般是在屏幕的最上方出现的,所以雪花的y坐标都是0,  其次,雪花的x坐标是随机的,他的范围是从屏幕的左边到右边,那么就是 0 ~ width. 这个width就是canvas的宽度,也就是浏览器的宽度

2,雪花的半径r, 设置为1 ~ 5之间的任意值

3,雪花下降的速度设置为3 ~ 5之间的随机速度,这里我做的下雪是垂直方向往下飘,你可以拓展,考虑风力影响( 这个时候肯定有水平方向的速度 )

有了这些初始化的参数之后,我们完善draw方法,绘制雪花:

1                 draw: function (cxt) {
2                     cxt.beginPath();
3                     cxt.fillStyle = 'white';
4                     cxt.arc(this.x, this.y + this.r, this.r, 0, Math.PI * 2, false);
5                     cxt.fill();
6                     cxt.closePath();
7                     this.update(cxt);
8                 },

参数cxt就是canvas的上下文,这个函数很简单,就是一个arc方法调用init中设置的值来画圆(雪花),在该方法的最后调用了一个update方法,他是干嘛的?他是更新雪花在垂直方向的速度

             update: function (cxt) {
                    if (this.y < height - this.r) {
                        this.y += this.vy;
                    } else {
                        this.init();
                    }
                }

在update方法中,我们做了边界判断: 雪花往下飘落的时候,肯定会消失,消失之后怎么处理?没有到达边界怎么处理?

canvas的高度减去雪花的半径,这就是雪花要消失时候的边界,所以this.y  < height - this.r  如果这个条件成立,那么说明雪花一直在飘着,我们就要把雪花的y方向的位置更新,雪花看起来(‘正在下雪’),当一个雪花快要消失的时候,我们再把他移动到初始的位置,这样看起来就是在圆圆不断的下雪,而不需要重新绘制雪花(如果这样做,肯定会影响性能,这个特效最后肯定会被卡死,这个小技巧很多类似的特效都会用到)。至此核心的流程已经搞定,接下来,我们就要大量的生成雪花了。

1             var snow = [];
2             for (var i = 0; i < 500; i++) {
3                 setTimeout(function () {
4                     var oSnow = new Snow();
5                     oSnow.init();
6                     snow.push(oSnow);
7                 }, 10 * i);
8             }

生成500个雪花,不是同时生成的,然后把这些雪花保存到数组snow中.

然后,开启定时器,让雪花不断的飘落吧,

关于requestAnimationFrame的使用,可以参考我的这篇文章:[js高手之路] html5新增的定时器requestAnimationFrame实战进度条

1              (function move() {
2                 oGc.clearRect(0, 0, width, height);
3                 for (var i = 0; i < snow.length; i++) {
4                     snow[i].draw(oGc);
5                 }
6                 requestAnimationFrame(move);
7             })();

完整的demo代码:

 1 <head>
 2     <meta charset="UTF-8">
 3     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 4     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 5     <title>雪花效果 - by ghostwu</title>
 6     <!-- <script src="lib.js"></script> -->
 7     <style>
 8         * {
 9             margin: 0;
10             padding: 0;
11         }
12 
13         body {
14             overflow: hidden;
15         }
16     </style>
17 </head>
18 
19 <body>
20     <script>
21         window.onload = function () {
22             var Canvas = function (w, h) {
23                 this.width = w;
24                 this.height = h;
25             }
26             Canvas.prototype = {
27                 init: function () {
28                     var oC = document.createElement("canvas");
29                     oC.setAttribute('width', this.width);
30                     oC.setAttribute('height', this.height);
31                     oC.setAttribute('id', 'canvas');
32                     oC.style.backgroundColor = '#000';
33                     document.body.appendChild(oC);
34                 }
35             }
36             var curWinWidth = window.innerWidth,
37                 curWinHeight = window.innerHeight;
38             var oCanvas = new Canvas(curWinWidth, curWinHeight);
39             oCanvas.init();
40 
41             var oC = document.querySelector('#canvas');
42             var width = oC.width, height = oC.height, oGc = oC.getContext('2d');
43 
44             function random(min, max) {
45                 return Math.random() * (max - min) + min;
46             }
47             var Snow = function () {
48 
49             }
50             Snow.prototype = {
51                 init: function () {
52                     this.x = random(0, width);
53                     this.y = 0;
54                     this.r = random(1, 5);
55                     this.vy = random(3, 5);
56                 },
57                 draw: function (cxt) {
58                     cxt.beginPath();
59                     cxt.fillStyle = 'white';
60                     cxt.arc(this.x, this.y + this.r, this.r, 0, Math.PI * 2, false);
61                     cxt.fill();
62                     cxt.closePath();
63                     this.update(cxt);
64                 },
65                 update: function (cxt) {
66                     if (this.y < height - this.r) {
67                         this.y += this.vy;
68                     } else {
69                         this.init();
70                     }
71                 }
72             }
73 
74             var snow = [];
75             for (var i = 0; i < 500; i++) {
76                 setTimeout(function () {
77                     var oSnow = new Snow();
78                     oSnow.init();
79                     snow.push(oSnow);
80                 }, 10 * i);
81             }
82 
83             (function move() {
84                 oGc.clearRect(0, 0, width, height);
85                 for (var i = 0; i < snow.length; i++) {
86                     snow[i].draw(oGc);
87                 }
88                 requestAnimationFrame(move);
89             })();
90         }
91     </script>
92 </body>
View Code

[js高手之路]html5canvas动画教程-匀速运动

匀速运动:指的是物体在一条直线上运动,并且物体在任何相等时间间隔内通过的位移都是相等的。其实就是匀速直线运动,它的特点是加速度为0,从定义可知,在任何相等的时间间隔内,速度大小和方向是相同的。1<head>2... 查看详情

[js高手之路]html5canvas系列教程-图片操作(drawimage,clip,createpattern)

 接着上文[js高手之路]html5canvas系列教程-文本样式(strokeText,fillText,measureText,textAlign,textBaseline)继续,本文介绍的内容是canvas开发,特别是游戏中,比较常用的内容:图片处理。在游戏中的资源大多数都是加载图片.一、canvas怎... 查看详情

[js高手之路]html5canvas系列教程-像素操作(反色,黑白,亮度,复古,蒙版,透明)

接着上文[js高手之路]html5canvas系列教程-状态详解(save与restore),相信大家都应该玩过美颜功能,而我们今天要讲的就是canvas强大的像素处理能力,通过像素处理,实现反色,黑白,亮度,复古,蒙版,透明等美颜效果.getImageData:... 查看详情

[js高手之路]html5canvas系列教程-文本样式(stroketext,filltext,measuretext,textalign,textbaseline)

接着上文线条样式[js高手之路]html5canvas系列教程-线条样式(lineWidth,lineCap,lineJoin,setLineDash)继续.canvas提供两种输出文本的方式:strokeText:描边文本fillText:填充文本fillStyle配合fillText使用,strokeStyle配合strokeText使用strokeText用法:cxt... 查看详情

[js高手之路]html5canvas动画教程-重力摩擦力加速抛物线运动

上节,我们讲了匀速运动,本节分享的运动就更有意思了:加速运动重力加速度抛物线运动摩擦力 加速运动:1<head>2<metacharset=‘utf-8‘/>3<style>4#canvas{5border:1pxdashed#aaa;6}7</style>8<scriptsrc="./ball.js"></script& 查看详情

[js高手之路]html5canvas教程-制作一个数码倒计时效果

效果图:这个实例主要注意:1,剩余时间的计算2,每个时间数字的绘制时间主要有0-9和一个冒号组成,用数组来表示(0:就是不画圆,1:就是画一个蓝色的圆)num.js文件:1vardigital=2[3[4[0,0,1,1,1,0,0],5[0,1,1,0,1,1,0],6[1,1,0,0,0,1,1],7[1,1,0,0,0,... 查看详情

[js高手之路]html5canvas动画教程-自己动手做一个类似windows的画图软件

这个绘图工具,我还没有做完,不过已经实现了总架构,以及常见的简易图形绘制功能:1,可以绘制直线,圆,矩形,正多边形【已完成】2,填充颜色和描边颜色的选择【已完成】3,描边和填充功能的选择【已完成】后续版本... 查看详情

[js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法

[js高手之路]深入浅出webpack教程系列索引目录:[js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数[js高手之路]深入浅出webpack教程系列2-配置文件webpack.config.js详解(上)[js高手之路]深入浅出webpack教程系列3-配置文... 查看详情

[js高手之路]深入浅出webpack教程系列6-插件使用之html-webpack-plugin配置(下)

上文我们对html-webpack-plugin的实例htmlWebpackPlugin进行了遍历分析,讲解了几个常用属性(inject,minify)以及自定义属性的添加,本文,我们继续深入他的配置选项的探讨.一、chunks选项这个属性非常有用,可以指定某个页面加载哪些chunk... 查看详情

[js高手之路]node.js模板引擎教程-jade速学与实战1

环境准备:全局安装jade: npminstalljade-g初始化项目package.json:npminit--yes安装完成之后,可以使用 jade--help查看jade的命令行用法一、在项目目录下新建index.jade文件inde.jade代码:1doctypehtml2html3head4meta(charset=‘utf-8‘)5title6body7h3欢... 查看详情

[js高手之路]node.js+jade+mongoose实战todolist(分页,ajax编辑,删除)

该系列文章索引:[js高手之路]nodejs系列课程-创建简易web服务器与文件读写[js高手之路]nodejs系列课程-图解express+supervisor+ejs用法[js高手之路]Node.js实现简易的爬虫-抓取博客所有文章列表信息[js高手之路]Node.js模板引擎教程-jade速学... 查看详情

html5canvas学习之路

三:Canvas的绘图(下)1.在画布上的合成合成是指如何精细控制画布上对象的透明度和分层效果。有两个属性可以控制合成操作:globalAlphaglobalAlphaCanvas属性用来表示透明度,它的默认值为1.0(完全不透明),并且可以设置从0.0到... 查看详情

[js高手之路]node.js模板引擎教程-jade速学与实战3-mixin

强大的mixinmixin类似于函数的功能,可以达到模块复用的效果mixinshow:定义一个类似函数的功能,名字叫show,里面的就是他的内容+show:调用show,每调用一次执行一次里面的内容编译之后的结果:mixin也可以传递参数编译之后的结果... 查看详情

[js高手之路]面向对象版本匀速运动框架

...教程]一步步开发一个可以定制配置的隔行变色小插件[js高手之路]匀速运动与实例实战(侧边栏,淡入淡出)[js高手之路]打造通用的匀速运动框架1<!DOCTYPEhtml>2<html>3<headlang="en">4<metacharset="UTF-8">5<title>通用的面向... 查看详情

[js高手之路]node.js模板引擎教程-jade速学与实战4-模板引用,继承,插件使用

一、block模块复用把需要复用的模块用block定义block后面跟上模块的名字,引用一次block内容就会被复用一次编译之后的结果:二,继承模板(extends) 在实际开发中,网站的头部,尾部一般都是公用的,我们可以通过jade的模板继... 查看详情

[js高手之路]node.js模板引擎教程-jade速学与实战2-流程控制,转义与非转义

一、转义与非转义jade模板文件代码:1doctypehtml2html3head4meta(charset=‘utf-8‘)5titlejade学习-byghostwu6body7h3转义与非转义8-varuserName=‘ghostwu‘9-varstr=‘<script>alert("ghostwu");</script>‘10div#{userName}11div 查看详情

[js高手之路]vue2.0基于vue-cli+webpack父子组件通信教程

在git命令行下,执行以下命令完成环境的搭建:1,npminstall--globalvue-cli 安装vue命令行工具2,vueinitwebpackvue-demo 使用vue命令生成一个webpack项目,项目名称为vue-demo 3,cdvue-demo切入项目4,npminstall安装package.json中的所有依... 查看详情

[js高手之路]深入浅出webpack教程系列7-(babel-loader,css-loader,style-loader)的用法

什么是loader呢,官方解释为文件的预处理器,通俗点说webpack在处理静态资源的时候,需要加载各种loader,比如,html文件,要用html-loader,css文件要用css-loader,style-loader等等.官方参考文档:https://webpack.js.org/loaders/我们从本文开始,... 查看详情