实例教程 HTML5 Canvas 超炫酷烟花绽放动画实现代码


Posted in HTML / CSS onNovember 05, 2014

这是一个很酷的HTML5 Canvas动画,它将模拟的是我们现实生活中烟花绽放的动画特效,效果非常逼真,但是毕竟是电脑模拟,带女朋友看就算了,效果还是差了点,呵呵。这个HTML5 Canvas动画有一点比较出色,就是其性能,Chrome上基本没有卡的感觉,就算你放出很多烟花也一样。

实例教程 HTML5 Canvas 超炫酷烟花绽放动画实现代码

下面我们来简单分析一下实现这款HTML5烟花特效的过程及代码,主要由HTML代码、CSS代码以及Javascript代码组成,当然javascript代码是最重要的。

HTML代码:

XML/HTML Code复制内容到剪贴板
  1. <div id=”gui”></div>  
  2. <div id=”canvas-container”> <div id=”mountains2″></div>    
  3. <div id=”mountains1″></div><div id=”skyline”></div> </div>  

HTML的结构非常简单,即构造了一个canvas容器,我们会利用JS在这个容器中生成一个Canvas对象。看最后的JS代码你就会知道了。

CSS代码:

CSS Code复制内容到剪贴板
  1. #canvas-container { background#000 url(bg.jpg); height400pxleft: 50%; margin: -200px 0 0 -300pxpositionabsolutetop: 50%; width600pxz-index: 2;   
  2. } canvas { cursorcrosshairdisplayblockpositionrelativez-index: 3;   
  3. } canvas:active { cursorcrosshair;   
  4. #skyline { backgroundurl(skyline.png) repeat-x 50% 0; bottombottom: 0; height135pxleft: 0; positionabsolutewidth: 100%; z-index: 1;       
  5. #mountains1 { backgroundurl(mountains1.png) repeat-x 40% 0; bottombottom: 0; height200pxleft: 0; positionabsolutewidth: 100%; z-index: 1;       
  6. #mountains2 { backgroundurl(mountains2.png) repeat-x 30% 0; bottombottom: 0; height250pxleft: 0; positionabsolutewidth: 100%; z-index: 1;       
  7. #gui { rightright: 0; positionfixedtop: 0; z-index: 3;   
  8. }  

CSS代码没什么特别,主要也就定义一下背景色和边框之类的。

接下来是最重要的Javascript代码。

Javascript代码:

JavaScript Code复制内容到剪贴板
  1. self.init = function(){       
  2.     self.dt = 0;   
  3.         self.oldTime = Date.now();   
  4.         self.canvas = document.createElement('canvas');                   
  5.         self.canvasContainer = $('#canvas-container'); var canvasContainerDisabled = document.getElementById('canvas-container');   
  6.         self.canvas.onselectstart = function() { return false;   
  7.         };   
  8.   
  9.         self.canvas.width = self.cw = 600;   
  10.         self.canvas.height = self.ch = 400;       
  11.   
  12.         self.particles = [];       
  13.         self.partCount = 30;   
  14.         self.fireworks = [];       
  15.         self.mx = self.cw/2;   
  16.         self.my = self.ch/2;   
  17.         self.currentHue = 170;   
  18.         self.partSpeed = 5;   
  19.         self.partSpeedVariance = 10;   
  20.         self.partWind = 50;   
  21.         self.partFriction = 5;   
  22.         self.partGravity = 1;   
  23.         self.hueMin = 150;   
  24.         self.hueMax = 200;   
  25.         self.fworkSpeed = 2;   
  26.         self.fworkAccel = 4;   
  27.         self.hueVariance = 30;   
  28.         self.flickerDensity = 20;   
  29.         self.showShockwave = false;   
  30.         self.showTarget = true;   
  31.         self.clearAlpha = 25;   
  32.   
  33.         self.canvasContainer.append(self.canvas);   
  34.         self.ctx = self.canvas.getContext('2d');   
  35.         self.ctx.lineCap = 'round';   
  36.         self.ctx.lineJoin = 'round';   
  37.         self.lineWidth = 1;   
  38.         self.bindEvents();               
  39.         self.canvasLoop();   
  40.   
  41.         self.canvas.onselectstart = function() { return false;   
  42.         };   
  43.   
  44.     };  

这段JS代码主要是往canvas容器中构造一个Canvas对象,并且对这个canvas对象的外观以及动画属性作了初始化。

JavaScript Code复制内容到剪贴板
  1. var Particle = function(x, y, hue){ this.x = x; this.y = y; this.coordLast = [   
  2.             {x: x, y: y},   
  3.             {x: x, y: y},   
  4.             {x: x, y: y}   
  5.         ]; this.angle = rand(0, 360); this.speed = rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance)); this.friction = 1 - self.partFriction/100; this.gravity = self.partGravity/2; this.hue = rand(hue-self.hueVariance, hue+self.hueVariance); this.brightness = rand(50, 80); this.alpha = rand(40,100)/100; this.decay = rand(10, 50)/1000; this.wind = (rand(0, self.partWind) - (self.partWind/2))/25; this.lineWidth = self.lineWidth;   
  6.     };   
  7.   
  8.     Particle.prototype.update = function(index){ var radians = this.angle * Math.PI / 180; var vx = Math.cos(radians) * this.speed; var vy = Math.sin(radians) * this.speed + this.gravity; this.speed *= this.friction; this.coordLast[2].x = this.coordLast[1].x; this.coordLast[2].y = this.coordLast[1].y; this.coordLast[1].x = this.coordLast[0].x; this.coordLast[1].y = this.coordLast[0].y; this.coordLast[0].x = this.x; this.coordLast[0].y = this.y; this.x += vx * self.dt; this.y += vy * self.dt; this.angle += this.wind; this.alpha -= this.decay; if(!hitTest(0,0,self.cw,self.ch,this.x-this.radius, this.y-this.radius, this.radius*2, this.radius*2) || this.alpha < .05){                       
  9.             self.particles.splice(index, 1);       
  10.         }               
  11.     };   
  12.   
  13.     Particle.prototype.draw = function(){ var coordRand = (rand(1,3)-1);   
  14.         self.ctx.beginPath();                                   
  15.         self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));   
  16.         self.ctx.lineTo(Math.round(this.x), Math.round(this.y));   
  17.         self.ctx.closePath();                   
  18.         self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';   
  19.         self.ctx.stroke(); if(self.flickerDensity > 0){ var inverseDensity = 50 - self.flickerDensity; if(rand(0, inverseDensity) === inverseDensity){   
  20.                 self.ctx.beginPath();   
  21.                 self.ctx.arc(Math.round(this.x), Math.round(this.y), rand(this.lineWidth,this.lineWidth+3)/2, 0, Math.PI*2, false)  self.ctx.closePath(); var randAlpha = rand(50,100)/100;   
  22.                 self.ctx.fillStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+randAlpha+')';   
  23.                 self.ctx.fill();   
  24.             }       
  25.         }   
  26.     };  

这段JS代码的功能是实现烟花爆炸后的小颗粒的绘制,从draw方法中可以看出,创建几个随机点,烟花颗粒即可在这个范围的随机点中散落。

JavaScript Code复制内容到剪贴板
  1. var Firework = function(startX, startY, targetX, targetY){ this.x = startX; this.y = startY; this.startX = startX; this.startY = startY; this.hitX = falsethis.hitY = falsethis.coordLast = [   
  2.             {x: startX, y: startY},   
  3.             {x: startX, y: startY},   
  4.             {x: startX, y: startY}   
  5.         ]; this.targetX = targetX; this.targetY = targetY; this.speed = self.fworkSpeed; this.angle = Math.atan2(targetY - startY, targetX - startX); this.shockwaveAngle = Math.atan2(targetY - startY, targetX - startX)+(90*(Math.PI/180)); this.acceleration = self.fworkAccel/100; this.hue = self.currentHue; this.brightness = rand(50, 80); this.alpha = rand(50,100)/100; this.lineWidth = self.lineWidth; this.targetRadius = 1;   
  6.     };   
  7.   
  8.     Firework.prototype.update = function(index){   
  9.         self.ctx.lineWidth = this.lineWidth;   
  10.   
  11.         vx = Math.cos(this.angle) * this.speed,   
  12.         vy = Math.sin(this.angle) * this.speed; this.speed *= 1 + this.acceleration; this.coordLast[2].x = this.coordLast[1].x; this.coordLast[2].y = this.coordLast[1].y; this.coordLast[1].x = this.coordLast[0].x; this.coordLast[1].y = this.coordLast[0].y; this.coordLast[0].x = this.x; this.coordLast[0].y = this.y; if(self.showTarget){ if(this.targetRadius < 8){ this.targetRadius += .25 * self.dt;   
  13.             } else { this.targetRadius = 1 * self.dt;       
  14.             }   
  15.         } if(this.startX >= this.targetX){ if(this.x + vx <= this.targetX){ this.x = this.targetX; this.hitX = true;   
  16.             } else { this.x += vx * self.dt;   
  17.             }   
  18.         } else { if(this.x + vx >= this.targetX){ this.x = this.targetX; this.hitX = true;   
  19.             } else { this.x += vx * self.dt;   
  20.             }   
  21.         } if(this.startY >= this.targetY){ if(this.y + vy <= this.targetY){ this.y = this.targetY; this.hitY = true;   
  22.             } else { this.y += vy * self.dt;   
  23.             }   
  24.         } else { if(this.y + vy >= this.targetY){ this.y = this.targetY; this.hitY = true;   
  25.             } else { this.y += vy * self.dt;   
  26.             }   
  27.         } if(this.hitX && this.hitY){ var randExplosion = rand(0, 9);   
  28.             self.createParticles(this.targetX, this.targetY, this.hue);   
  29.             self.fireworks.splice(index, 1);                       
  30.         }   
  31.     };   
  32.   
  33.     Firework.prototype.draw = function(){   
  34.         self.ctx.lineWidth = this.lineWidth; var coordRand = (rand(1,3)-1);                       
  35.         self.ctx.beginPath();                               
  36.         self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));   
  37.         self.ctx.lineTo(Math.round(this.x), Math.round(this.y));   
  38.         self.ctx.closePath();   
  39.         self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';   
  40.         self.ctx.stroke(); if(self.showTarget){   
  41.             self.ctx.save();   
  42.             self.ctx.beginPath();   
  43.             self.ctx.arc(Math.round(this.targetX), Math.round(this.targetY), this.targetRadius, 0, Math.PI*2, false)   
  44.             self.ctx.closePath();   
  45.             self.ctx.lineWidth = 1;   
  46.             self.ctx.stroke();   
  47.             self.ctx.restore();   
  48.         } if(self.showShockwave){   
  49.             self.ctx.save();   
  50.             self.ctx.translate(Math.round(this.x), Math.round(this.y));   
  51.             self.ctx.rotate(this.shockwaveAngle);   
  52.             self.ctx.beginPath();   
  53.             self.ctx.arc(0, 0, 1*(this.speed/5), 0, Math.PI, true);   
  54.             self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+rand(25, 60)/100+')';   
  55.             self.ctx.lineWidth = this.lineWidth;   
  56.             self.ctx.stroke();   
  57.             self.ctx.restore();   
  58.         }                                    
  59.     };  

这段JS代码是创建烟花实例的,我们也可以从draw方法中看出,当我们鼠标点击画布中的某点时,烟花发射的目的地就在那个点上。

这款HTML5 Canvas烟花效果的核心代码就是这样,谢谢阅读,希望能帮到大家,请继续关注三水点靠木,我们会努力分享更多优秀的文章。

HTML / CSS 相关文章推荐
CSS3网格的三个新特性详解
Apr 04 HTML / CSS
CSS3 Pie工具推荐--让IE6-8支持一些优秀的CSS3特性
Sep 02 HTML / CSS
基于CSS3实现图片模糊过滤效果
Nov 19 HTML / CSS
纯css3实现宠物小鸡实例代码
Oct 08 HTML / CSS
CSS3贝塞尔曲线示例:创建链接悬停动画效果
Nov 19 HTML / CSS
html5构建触屏网站之网站尺寸探讨
Jan 07 HTML / CSS
基于HTML5 FileSystem API的使用介绍
Apr 24 HTML / CSS
html5使用canvas绘制文字特效
Dec 15 HTML / CSS
使用分层画布来优化HTML5渲染的教程
May 08 HTML / CSS
详解HTML5中的元素与元素
Aug 17 HTML / CSS
css animation配合SVG制作能量流动效果
Mar 24 HTML / CSS
css中有哪些方式可以隐藏页面元素及区别
Jun 16 HTML / CSS
HTML5制作3D爱心动画教程 献给女友浪漫的礼物
Nov 05 #HTML / CSS
html5 css3实例教程 一款html5和css3实现的小机器人走路动画
Oct 20 #HTML / CSS
实例教程 利用html5和css3打造一款创意404页面
Oct 20 #HTML / CSS
基于html5实现的图片墙效果
Oct 16 #HTML / CSS
html5版canvas自由拼图实例
Oct 15 #HTML / CSS
HTML5地理定位实例
Oct 15 #HTML / CSS
IE9对HTML5中部分属性不支持的原因分析
Oct 15 #HTML / CSS
You might like
PHP array_flip() 删除重复数组元素专用函数
2010/05/16 PHP
php 大数据量及海量数据处理算法总结
2011/05/07 PHP
php实现水仙花数示例分享
2014/04/03 PHP
30个php操作redis常用方法代码例子
2014/07/05 PHP
PHP中用mysqli面向对象打开连接关闭mysql数据库的方法
2016/11/05 PHP
jquery 学习之二 属性(类)
2010/11/25 Javascript
深入理解JavaScript系列(10) JavaScript核心(晋级高手必读篇)
2012/01/15 Javascript
Jquery实现网页跳转或用命令打开指定网页的解决方法
2013/07/09 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
2014/03/05 Javascript
JavaScript中使用sencha gridpanel 编辑单元格、改变单元格颜色
2015/11/26 Javascript
详解JavaScript实现设计模式中的适配器模式的方法
2016/05/18 Javascript
js实现hashtable的赋值、取值、遍历操作实例详解
2016/12/25 Javascript
javascript防篡改对象实例详解
2017/04/10 Javascript
基于Bootstrap实现城市三级联动
2017/11/23 Javascript
解决layui上传文件提示上传异常,实际文件已经上传成功的问题
2018/08/19 Javascript
微信小程序授权登录解决方案的代码实例(含未通过授权解决方案)
2019/05/10 Javascript
js实现图片推拉门效果代码实例
2019/05/18 Javascript
解决layui的radio属性或别的属性没显示出来的问题
2019/09/26 Javascript
[01:30:15]DOTA2-DPC中国联赛 正赛 Ehome vs Aster BO3 第二场 2月2日
2021/03/11 DOTA
用Python的Django框架编写从Google Adsense中获得报表的应用
2015/04/17 Python
python对csv文件追加写入列的方法
2019/08/01 Python
Python列表删除元素del、pop()和remove()的区别小结
2019/09/11 Python
马来西亚时装购物网站:ZALORA马来西亚
2017/03/14 全球购物
Tech21美国/加拿大:英国NO.1防摔保护壳品牌
2018/01/20 全球购物
意大利和国际最佳时尚品牌:Drestige
2019/12/28 全球购物
软件测试常见笔试题
2012/02/04 面试题
造价工程师个人求职信
2013/09/21 职场文书
项目投资意向书
2014/04/01 职场文书
车队司机个人自我鉴定
2014/04/17 职场文书
行政专员求职信范文
2014/05/03 职场文书
关于爱国的演讲稿
2014/05/07 职场文书
推广普通话演讲稿
2014/05/23 职场文书
学校工会工作总结2015
2015/05/19 职场文书
MySQL的Query Cache图文详解
2021/07/01 MySQL
Python编程编写完善的命令行工具
2021/09/15 Python
你真的会用Mysql的explain吗
2022/03/31 MySQL