利用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>
[js高手之路]html5 canvas动画教程 - 下雪效果
原文地址:http://www.cnblogs.com/ghostwu/p/7690639.html