昨天冬至,又到了白色相簿的季节了,︿( ̄︶ ̄)︿笑,后天就是圣诞了,安安心心做个剩蛋老人吧(ノへ ̄、)。
好了好了,重庆还是没下雪,冷着不下雪,感觉好亏。既然不下,那就只有自己写点雪花了。
canvas这个东西一直是想深入学习的,做出来的东西各种炫酷吊炸天,但是没啥时间,就只会点小东西,大家将就着看吧:
首先既然是用canvas,那么结构就非常简单啦,html什么都不用写,用js创建canvas。
我们把一张背景图放在body上,然后在canvas上进行雪花的绘制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| *{ margin: 0; padding: 0; } html{ width: 100%; height: 100%; } body{ width: 100%; height: 100%; background: url("./xh.jpg") center no-repeat; overflow: hidden; }
|
这次就不用es6的写法了,用prototype吧:
首先我们用requestAnimationFrame绘制动画的,先把兼容性搞一下,再创建函数snowFall,设置一下默认参数,maxFlake、flakeSize和fallSpeed,在进行初始化时,可以通过new snowFall()传入这三个参数改变雪花的样式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function(callback) { setTimeout(callback, 1000 / 60); }; function snowFall(snow) { snow = snow || {}; this.maxFlake = snow.maxFlake || 500; this.flakeSize = snow.flakeSize || 10; this.fallSpeed = snow.fallSpeed || 1; this.flakes = []; }
|
然后我们在这个函数上添加一个start方法,调用此方法开始创建画布绘制雪花,出现下雪效果:
1 2 3 4 5 6 7 8 9
| snowFall.prototype.start = function(){ snowCanvas.apply(this); createFlakes.apply(this); drawSnow.apply(this); }
|
接下来开始创建画布了,建立一个canvas放入body中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function snowCanvas() { var snowcanvas = document.createElement("canvas"); snowcanvas.id = "snowfall"; snowcanvas.width = window.innerWidth; snowcanvas.height = document.body.clientHeight || document.documentElement.clientHeight; document.getElementsByTagName("body")[0].appendChild(snowcanvas); this.canvas = snowcanvas; this.ctx = snowcanvas.getContext("2d"); window.onresize = function () { snowcanvas.width = window.innerWidth; snowcanvas.height = window.innerHeight; } }
|
接着创建雪花的形状,这里循环一下要绘制的雪花,用一个雪运动对象设置每个雪花的参数,然后将雪花放入雪花集合中:
1 2 3 4 5 6
| function createFlakes() { for (var i = 0; i < this.maxFlake; i++) { this.flakes.push(new flakeMove(this.canvas.width, this.canvas.height, this.flakeSize, this.fallSpeed)) } }
|
雪花运动对象,用于生成每个雪花的一系列参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function flakeMove(canvasWidth, canvasHeight, flakeSize, fallSpeed) { this.canvasw = canvasWidth; this.canvash = canvasHeight; this.x = Math.floor(Math.random() * canvasWidth); this.y = Math.floor(Math.random() * canvasHeight); this.size = Math.random() * flakeSize + 2; this.maxSize = flakeSize; this.speed = Math.random() * 1 + fallSpeed; this.fallSpeed = fallSpeed; this.velY = this.speed; this.velX = 0; this.stepSize = Math.random() / 100; }
|
在雪的运动对象上添加一个render方法,用于生成雪的形状
1 2 3 4 5 6 7 8 9 10 11 12 13
| flakeMove.prototype.render = function (ctx) { var snowFlake = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size); snowFlake.addColorStop(0, "rgba(255, 255, 255, 0.9)"); snowFlake.addColorStop(.5, "rgba(255, 255, 255, 0.5)"); snowFlake.addColorStop(1, "rgba(255, 255, 255, 0)"); ctx.save(); ctx.fillStyle = snowFlake; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); ctx.restore(); };
|
在雪的运动对象上添加一个雪花的运动方法,根据传入的参数不同,来让雪向左向右运动,当雪花飞到了边界后,调用reset方法重置这个雪花的状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| flakeMove.prototype.update = function (n) { var x = this.x, y = this.y; if (n) { this.velX += this.stepSize; } else { this.velX -= this.stepSize; } this.y += this.velY; this.x += this.velX; if (this.x >= this.canvasw || this.x <= 0 || this.y >= this.canvaswh || this.y <= 0) { this.reset(this.canvasw, this.canvash) } }; flakeMove.prototype.reset = function (width, height) { this.x = Math.floor(Math.random() * width); this.y = 0; this.size = Math.random() * this.maxSize + 2; this.speed = Math.random() * 1 + this.fallSpeed; this.velY = this.speed; this.velX = 0; };
|
雪花对象设置完毕后,我们开始画雪了,每次绘制前我们都要清空一下画布,然后根据雪花的集合进行遍历,调用函数让一部分雪花向左飘,一部分向右飘,然后用requestAnimationFrame继续调用画雪的函数,一帧一帧绘制雪花:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function drawSnow() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); for (var e = 0; e < this.maxFlake; e++) { if (e % 3 == 0) { this.flakes[e].update(0); this.flakes[e].render(this.ctx); } else { this.flakes[e].update(1); this.flakes[e].render(this.ctx); }; } this.loop = requestAnimationFrame(function () { drawSnow.apply(this); }.bind(this)); }
|
最后我们 new snowFall(),最多绘制100个雪花,然后调用start方法,雪花就开始飞舞了:
1 2 3 4 5
| var snow = new snowFall({ maxFlake: 100 }); snow.start();
|
效果展示:
本文代码地址:链接