电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

JavaScript實現(xiàn)煙花綻放動畫效果

瀏覽:120日期:2023-10-18 18:52:41

先編寫一個煙花綻放的動畫效果。

放煙花時,一個煙花可分為兩個階段:(1)煙花上升到空中;(2)煙花炸開成碎片,炸開的碎片慢慢消散。

為此抽象出兩個對象類:Firework和Particle。其中,F(xiàn)irework用于表示一個煙花對象,Particle用于表示一個煙花炸開后的各碎片。

Firework對象類定義6個屬性:表示煙花上升軌跡中各點(diǎn)的坐標(biāo)(x,y)、煙花弧狀軌跡的偏轉(zhuǎn)角度angle、上升階段水平和垂直方向的位移改變量xSpeed和ySpeed、煙花的色彩色相hue。

坐標(biāo)屬性值y的初始值取畫布的高度,表示煙花從地面上升到空中,其余各屬性的初始值采用隨機(jī)數(shù)確定。具體定義如下:

function Firework() { this.x = canvas.width/4*(1+3*Math.random()); this.y = canvas.height - 15; this.angle = Math.random() * Math.PI / 4 - Math.PI / 6; this.xSpeed = Math.sin(this.angle) *(6+Math.random()*7); this.ySpeed = -Math.cos(this.angle) *(6+Math.random()*7); this.hue = Math.floor(Math.random() * 360); }

Firework對象類定義3個方法:繪制煙花上升軌跡的方法draw()、煙花上升時坐標(biāo)改變方法update()和煙花炸開方法explode()。繪制煙花軌跡時,在各點(diǎn)(x,y)處繪制一個寬度為5、高度為15的填充小矩形表示一個軌跡點(diǎn)。煙花上升時,垂直方向速度ySpeed初始值為負(fù)的,每次上升時,ySpeed加上一個正值,表示上升在減速,當(dāng)ySpeed的值大于0時,煙花上升到頂了(不能再上升),就炸開為70個碎片。具體方法的實現(xiàn)見后面的HTML文件內(nèi)容。

Particle對象類定義8個屬性:表示碎片散開軌跡中各點(diǎn)的坐標(biāo)(x,y)、碎片弧狀軌跡的偏轉(zhuǎn)角度angle、散開時水平和垂直方向的位移改變量xSpeed和ySpeed、碎片的色彩色相hue、表示碎片小圓的半徑size、碎片的亮度lightness。

function Particle(x,y,hue) { this.x = x; this.y = y; this.hue = hue; this.lightness = 50; this.size = 15 + Math.random() * 10; this.angle = Math.random() * 2 * Math.PI; this.xSpeed = Math.cos(this.angle) *(1+Math.random() * 6); this.ySpeed = Math.sin(this.angle) *(1+Math.random() * 6); }

Particle對象類定義2個方法:繪制碎片散開軌跡的方法draw()、碎片散開時坐標(biāo)改變方法update()。碎片散開時逐漸變小(屬性size值減量),當(dāng)size值小于1時,從碎片數(shù)組中刪除該碎片,表示碎片已消亡。

定義兩個數(shù)組var fireworks=[];和var particles=[];分別存儲煙花對象和炸開的碎片對象。

模擬動畫的函數(shù)loop中,每隔一段時間(用count計數(shù)來實現(xiàn))向fireworks數(shù)組中添加一個煙花對象,煙花對象上升到頂炸開后,從fireworks數(shù)組中刪除該對象元素,然后向particles數(shù)組中添加70個碎片對象。

遍歷兩個數(shù)組的各對象,分別調(diào)用它們的draw()和update()方法。

編寫的完整HTML文件內(nèi)容如下。

<html> <head> <title>煙花綻放</title> </head><body><canvas style='border:3px double #996633;background:black;'></canvas><script type='text/javascript'> var canvas=document.getElementById(’myCanvas’); ctx= canvas.getContext(’2d’); var fireworks=[]; var particles=[]; var counter = 0; function Firework() { this.x = canvas.width/4*(1+3*Math.random()); this.y = canvas.height - 15; this.angle = Math.random() * Math.PI / 4 - Math.PI / 6; this.xSpeed = Math.sin(this.angle) *(6+Math.random()*7); this.ySpeed = -Math.cos(this.angle) *(6+Math.random()*7); this.hue = Math.floor(Math.random() * 360); } Firework.prototype.draw= function() { ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(Math.atan2(this.ySpeed, this.xSpeed) + Math.PI / 2); ctx.fillStyle =`hsl(${this.hue}, 100%, 50%)`; ctx.fillRect(0, 0, 5, 15); ctx.restore(); } Firework.prototype.update= function() { this.x = this.x + this.xSpeed; this.y = this.y + this.ySpeed; this.ySpeed += 0.1; } Firework.prototype.explode= function() { for (var i = 0; i < 70; i++) { particles.push(new Particle(this.x, this.y, this.hue)); } } function Particle(x,y,hue) { this.x = x; this.y = y; this.hue = hue; this.lightness = 50; this.size = 15 + Math.random() * 10; this.angle = Math.random() * 2 * Math.PI; this.xSpeed = Math.cos(this.angle) *(1+Math.random() * 6); this.ySpeed = Math.sin(this.angle) *(1+Math.random() * 6); } Particle.prototype.draw= function() { ctx.fillStyle = `hsl(${this.hue}, 100%, ${this.lightness}%)`; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); ctx.closePath(); ctx.fill(); } Particle.prototype.update= function(index) { this.ySpeed += 0.05; this.size = this.size*0.95; this.x = this.x + this.xSpeed; this.y = this.y + this.ySpeed; if (this.size<1) { particles.splice(index,1); } } function loop() { ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; ctx.fillRect(0,0,canvas.width,canvas.height); counter++; if (counter==15) { fireworks.push(new Firework()); counter=0; } var i=fireworks.length; while (i--) { fireworks[i].draw(); fireworks[i].update(); if (fireworks[i].ySpeed > 0) { fireworks[i].explode(); fireworks.splice(i, 1); } } var i=particles.length; while (i--) {particles[i].draw(); particles[i].update(i); } requestAnimationFrame(loop); } loop();</script></body> </html>

在瀏覽器中打開包含這段HTML代碼的html文件,可以看到在瀏覽器窗口中呈現(xiàn)出如圖所示的煙花綻放動畫效果。

JavaScript實現(xiàn)煙花綻放動畫效果

實現(xiàn)了煙花綻放的效果,我們還可以繼續(xù)讓一定區(qū)域內(nèi)的綻放的煙花碎片拼成“Happy New Year”粒子文本。

編寫如下的HTML代碼。

<html> <head> <title>迎新年煙花綻放</title> <style> body { margin: 0; background: black; } canvas { position: absolute; }</style></head><body><canvas id='myCanvas1'></canvas><canvas id='myCanvas2'></canvas><canvas id='myCanvas3'></canvas><script type='text/javascript'> function Particle(x, y, hue) { this.x = x; this.y = y; this.hue = hue; this.lightness = 50; this.size = 15 + Math.random() * 10; this.angle = Math.random() * 2 * Math.PI; this.xSpeed = Math.cos(this.angle) * (1 + Math.random() * 6); this.ySpeed = Math.sin(this.angle) * (1 + Math.random() * 6); this.target = getTarget(); this.timer = 0; } Particle.prototype.draw= function() { ctx2.fillStyle =`hsl(${this.hue}, 100%, ${this.lightness}%)`; ctx2.beginPath(); ctx2.arc(this.x, this.y, this.size, 0, 2 * Math.PI); ctx2.closePath(); ctx2.fill(); } Particle.prototype.update= function(idx) { if (this.target) { var dx = this.target.x - this.x; var dy = this.target.y - this.y; var dist = Math.sqrt(dx * dx + dy * dy); var a = Math.atan2(dy, dx); var tx = Math.cos(a) * 5; var ty = Math.sin(a) * 5; this.size = lerp(this.size, 1.5, 0.05); if (dist < 5) { this.lightness = lerp(this.lightness, 100, 0.01); this.xSpeed = this.ySpeed = 0; this.x = lerp(this.x, this.target.x + fidelity / 2, 0.05); this.y = lerp(this.y, this.target.y + fidelity / 2, 0.05); this.timer += 1; } else if (dist < 10) { this.lightness = lerp(this.lightness, 100, 0.01); this.xSpeed = lerp(this.xSpeed, tx, 0.1); this.ySpeed = lerp(this.ySpeed, ty, 0.1); this.timer += 1; } else { this.xSpeed = lerp(this.xSpeed, tx, 0.02); this.ySpeed = lerp(this.ySpeed, ty, 0.02); } } else { this.ySpeed += 0.05; this.size = this.size*0.95; if (this.size<1) { particles.splice(idx,1); } } this.x = this.x + this.xSpeed; this.y = this.y + this.ySpeed; } function Firework() { this.x = canvas2.width*(1+ 3*Math.random())/4; this.y = canvas2.height - 15; this.angle = Math.random() * Math.PI / 4 - Math.PI / 6; this.xSpeed = Math.sin(this.angle) * (6 + Math.random() * 7); this.ySpeed = -Math.cos(this.angle) * (6 + Math.random() * 7); this.hue = Math.floor(Math.random() * 360); } Firework.prototype.draw= function() { ctx2.save(); ctx2.translate(this.x, this.y); ctx2.rotate(Math.atan2(this.ySpeed, this.xSpeed) + Math.PI / 2); ctx2.fillStyle = `hsl(${this.hue}, 100%, 50%)`; ctx2.fillRect(0, 0, 5, 15); ctx2.restore(); } Firework.prototype.update= function() { this.x = this.x + this.xSpeed; this.y = this.y + this.ySpeed; this.ySpeed += 0.1; } Firework.prototype.explode= function() { for (var i = 0; i < 70; i++) { particles.push(new Particle(this.x, this.y, this.hue)); } } function lerp(a, b, t) { return Math.abs(b - a)> 0.1 ? a + t * (b - a) : b; } function getTarget() { if (targets.length > 0) { var idx = Math.floor(Math.random() * targets.length); var { x, y } = targets[idx]; targets.splice(idx, 1); x += canvas2.width / 2 - textWidth / 2; y += canvas2.height / 2 - fontSize / 2; return { x, y }; } } var canvas1=document.getElementById(’myCanvas1’); ctx1= canvas1.getContext(’2d’); var canvas2=document.getElementById(’myCanvas2’); ctx2= canvas2.getContext(’2d’); var canvas3=document.getElementById(’myCanvas3’); ctx3= canvas3.getContext(’2d’); var fontSize = 200; var fireworks = []; var particles = []; var targets = []; var fidelity = 3; var counter = 0; canvas2.width = canvas3.width = window.innerWidth; canvas2.height = canvas3.height = window.innerHeight; ctx1.fillStyle = ’#000’; var text = ’Happy New Year’; var textWidth = 999999; while (textWidth > window.innerWidth) { ctx1.font = `900 ${fontSize--}px Arial`; textWidth = ctx1.measureText(text).width; } canvas1.width = textWidth; canvas1.height = fontSize * 1.5; ctx1.font = `900 ${fontSize}px Arial`; ctx1.fillText(text, 0, fontSize); var imgData = ctx1.getImageData(0, 0, canvas1.width, canvas1.height); for (var i = 0, max = imgData.data.length; i < max; i += 4) { var alpha = imgData.data[i + 3]; var x = Math.floor(i / 4) % imgData.width; var y = Math.floor(i / 4 / imgData.width); if (alpha && x % fidelity === 0 && y % fidelity === 0) { targets.push({ x, y }); } } ctx3.fillStyle = ’#FFF’; ctx3.shadowColor = ’#FFF’; ctx3.shadowBlur = 25; function loop() { ctx2.fillStyle = 'rgba(0, 0, 0, .1)'; ctx2.fillRect(0, 0, canvas2.width, canvas2.height); counter += 1; if (counter==15) { fireworks.push(new Firework()); counter=0; } var i=fireworks.length; while (i--) { fireworks[i].draw(); fireworks[i].update(); if (fireworks[i].ySpeed > 0) { fireworks[i].explode(); fireworks.splice(i, 1); } } var i=particles.length; while (i--) {particles[i].draw(); particles[i].update(i); if (particles[i].timer >= 100 || particles[i].lightness >= 99) { ctx3.fillRect(particles[i].target.x, particles[i].target.y, fidelity + 1, fidelity + 1); particles.splice(i, 1); } } requestAnimationFrame(loop); } loop();</script></body> </html>

在瀏覽器中打開包含這段HTML代碼的html文件,可以看到在瀏覽器窗口中呈現(xiàn)出如圖所示的煙花綻放迎新年動畫效果。圖2中為了控制圖片的大小,刪除了大量的中間幀,因此和實際運(yùn)行的效果有所不同。

JavaScript實現(xiàn)煙花綻放動畫效果

以上就是JavaScript實現(xiàn)煙花綻放動畫效果的詳細(xì)內(nèi)容,更多關(guān)于JavaScript動畫效果的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 顺景erp系统_erp软件_erp软件系统_企业erp管理系统-广东顺景软件科技有限公司 | 非标压力容器_碳钢储罐_不锈钢_搪玻璃反应釜厂家-山东首丰智能环保装备有限公司 | 广州监控安装公司_远程监控_安防弱电工程_无线wifi覆盖_泉威安防科技 | 涂层测厚仪_光泽度仪_uv能量计_紫外辐照计_太阳膜测试仪_透光率仪-林上科技 | 云阳人才网_云阳招聘网_云阳人才市场_云阳人事人才网_云阳人家招聘网_云阳最新招聘信息 | 衡阳耐适防护科技有限公司——威仕盾焊接防护用品官网/焊工手套/焊接防护服/皮革防护手套 | 升降炉_真空气氛炉_管式电阻炉厂家-山东中辰电炉有限公司 | 光栅尺厂家_数显表维修-苏州泽升精密机械 | 深圳办公室装修-写字楼装修设计-深圳标榜装饰公司 | 涂层测厚仪_光泽度仪_uv能量计_紫外辐照计_太阳膜测试仪_透光率仪-林上科技 | 新疆散热器,新疆暖气片,新疆电锅炉,光耀暖通公司 | 济南保安公司加盟挂靠-亮剑国际安保服务集团总部-山东保安公司|济南保安培训学校 | 知企服务-企业综合服务(ZiKeys.com)-品优低价、种类齐全、过程管理透明、速度快捷高效、放心服务,知企专家! | 快干水泥|桥梁伸缩缝止水胶|伸缩缝装置生产厂家-广东广航交通科技有限公司 | 吲哚菁绿衍生物-酶底物法大肠菌群检测试剂-北京和信同通科技发展有限公司 | 百方网-百方电气网,电工电气行业专业的B2B电子商务平台 | 北京普辉律师事务所官网_北京律师24小时免费咨询|法律咨询 | 贵州科比特-防雷公司厂家提供贵州防雷工程,防雷检测,防雷接地,防雷设备价格,防雷产品报价服务-贵州防雷检测公司 | 连栋温室大棚建造厂家-智能玻璃温室-薄膜温室_青州市亿诚农业科技 | 大数据营销公司_舆情监测软件_上海SEO公司-文军营销官网 | 27PR跨境电商导航 | 专注外贸跨境电商 | 安徽控制器-合肥船用空调控制器-合肥家电控制器-合肥迅驰电子厂 安徽净化板_合肥岩棉板厂家_玻镁板厂家_安徽科艺美洁净科技有限公司 | 超声波破碎仪-均质乳化机(供应杭州,上海,北京,广州,深圳,成都等地)-上海沪析实业有限公司 | 阁楼货架_阁楼平台_仓库仓储设备_重型货架_广州金铁牛货架厂 | 华溶溶出仪-Memmert稳定箱-上海协烁仪器科技有限公司 | 东风体检车厂家_公共卫生体检车_医院体检车_移动体检车-锦沅科贸 | 桂林腻子粉_内墙外墙抗裂砂浆腻子粉推荐广西鑫达涂料厂家供应 | 上海刑事律师|刑事辩护律师|专业刑事犯罪辩护律师免费咨询-[尤辰荣]金牌上海刑事律师团队 | 艾默生变频器,艾默生ct,变频器,ct驱动器,广州艾默生变频器,供水专用变频器,风机变频器,电梯变频器,艾默生变频器代理-广州市盟雄贸易有限公司官方网站-艾默生变频器应用解决方案服务商 | 航空障碍灯_高中低光强航空障碍灯_民航许可认证航空警示灯厂家-东莞市天翔航天科技有限公司 | 高低温万能试验机_拉力试验机_拉伸试验机-馥勒仪器科技(上海)有限公司 | 【德信自动化】点胶机_全自动点胶机_自动点胶机厂家_塑料热压机_自动螺丝机-深圳市德信自动化设备有限公司 | 磁力抛光研磨机_超声波清洗机厂家_去毛刺设备-中锐达数控 | 健身器材-健身器材厂家专卖-上海七诚健身器材有限公司 | 沈阳液压泵_沈阳液压阀_沈阳液压站-沈阳海德太科液压设备有限公司 | 冷却塔厂家_冷却塔维修_冷却塔改造_凉水塔配件填料公司- 广东康明节能空调有限公司 | 耐酸碱胶管_耐腐蚀软管总成_化学品输送软管_漯河利通液压科技耐油耐磨喷砂软管|耐腐蚀化学软管 | 大立教育官网-一级建造师培训-二级建造师培训-造价工程师-安全工程师-监理工程师考试培训 | 东莞注册公司-代办营业执照-东莞公司注册代理记账-极刻财税 | 江苏皓越真空设备有限公司 | 阻燃剂-氢氧化镁-氢氧化铝-沥青阻燃剂-合肥皖燃新材料 |