使用canvas实现雪花效果

本文记载了如何使用canvas来实现雪花效果:

效果图如下:

使用canvas实现雪花效果

本demo设计到的知识点有canvas的状态的保存于恢复,canvas的绘制径向渐变,使用html提供的被誉为神器的requestAnimationFrame 

 html主要代码如下:

<canvas class="myblog" id="mycanvas"> 
</canvas>

主要的js代码如下:

// HTML5新增的定时器requestAnimationFrame
			window.requestAnimationFrame = (function() {
				return window.requestAnimationFrame ||
					   window.webkitRequestAnimationFrame ||
					   window.mozRequestAnimationFrame ||
					   window.oRequestAnimationFrame ||
					   window.msRequestAnimationFrame ||
					   function (callback) {
						  setTimeout(callback, 1000/ 60);
						}
			})();
						
			window.onload = function(){ 
				// 获取浏览器的长宽 
				var b_width = window.screen.width;
				var b_height = window.screen.height; 
				var c = document.getElementById("mycanvas");
				c.width = b_width;
				c.height = b_height;   
				// 获取canvas 的2d上下文
				var ctx = c.getContext("2d");
				// 绘制背景
				drawmybg(ctx, c.width, c.height);				
				
				// 所有的雪花
				const snows = [];
				// 下落的加速度
				const G = 0.01;  
				// 速度限制(X,Y)
				const SPEED_LIMIT_X = 1;
				const SPEED_LIMIT_Y = 1;
				
				// 定时器定时的间隔(新增snow)
				let tickerCount = 150;
				// 定时器计数
				let ticker = 0;
				
				// 当前时间
				let lastTime = Date.now();
				// 执行循环的时间
				let deltaTime = 0;
				
				// 获取图片资源
				let snowImage = new Image();
				snowImage.src = './snow.png';
				
				// 开始绘制
				loop();
				
				
				// 循环绘制
				function loop(){
					requestAnimationFrame(loop);
					// 清除画板
					ctx.clearRect(0, 0, c.width, c.height);  
					
					// 计算时间间隔累加tricker
					const now = Date.now();
					deltaTime = now - lastTime;
					lastTime = now;
					ticker += deltaTime;
					
					// 当超过tickcount时候,新增snow
					if(ticker > tickerCount){
						snows.push(new Snow(
							Math.random()*c.width,
							0,
							Math.random()*5 + 5
						));
						ticker %= tickerCount;
					}
				 
					// 绘制背景
					drawmybg(ctx, c.width, c.height);
					// 绘制雪花
					snows.map(function(s,i){
						s.update();
						s.draw();
						// 如果雪花到底部删除
						if(s.y>c.height){ 
							snows.splice(i, 1);
						}
					});
				} 
				
				// 定义雪花实体
				function Snow(x, y, radius){
					this.x = x;
					this.y = y;
					this.sx = 0;
					this.sy = 0;
					this.radius = radius;
					this.deg = 0;
					this.ax = Math.random()<0.5? 0.005:-0.005;
				}

				// 定义雪花的状态
				Snow.prototype.update = function(){
					const degr = Math.random()*0.6 + 0.2;

					// x方向调整
					this.sx += this.ax;
					if(this.sx >= SPEED_LIMIT_X || this.sx <= -SPEED_LIMIT_X){
						this.ax *= -1;
					}
					
					// y方向调整
					if(this.sy < SPEED_LIMIT_Y){
						this.sy += G;
					}
					
					// 更新snow参数
					this.x += this.sx;
					this.y += this.sy; 
					this.deg += degr; 
				}

				// 绘制雪花
				Snow.prototype.draw = function(){ 
					const radius = this.radius;
					ctx.save();
					ctx.translate(this.x, this.y);
					ctx.rotate(this.deg * Math.PI / 180);
					ctx.drawImage(snowImage, -radius, -radius, radius*2, radius*2);
					ctx.restore();
				}
				
				// 绘制背景
				function drawmybg(ctx,W, H){ 
					ctx.save();
					var grd = ctx.createRadialGradient(W/2,H/2, 1, W/2, H/2, H);
					grd.addColorStop(0,"white"); 
					grd.addColorStop(1,"#0a2a39"); 
					ctx.fillStyle = grd;
					ctx.fillRect(0, 0, W, H);
					ctx.restore();
				}
			}  

另外代码用用到了snow.png这个根据个人的喜好到网上去找吧~