跨年烟花-Html5实现_附完整源码【可直接运行】

文章目录

  • 前言
    • 目录结构
    • ⚫完整源码
    • 源码分析
      • 注意事项
  • 总结

前言

随着科技的进步和互联网的普及,人们对于跨年庆祝的方式也在不断变化。传统的烟花燃放虽然美丽,但存在环境污染、安全隐患等问题。为了满足人们对于跨年庆祝的需求,同时避免传统烟花的弊端,我们开发了一个基于Html5的跨年烟花模拟项目。

这个项目的目标是利用Html5的Canvas技术,模拟出逼真的烟花效果,让用户在网页上欣赏到绚丽多彩的烟花盛宴。同时,通过交互式设计,让用户能够与烟花互动,增加趣味性。

项目开发过程中,我们面临的主要挑战是如何在有限的浏览器环境中,实现逼真的烟花效果。为此,我们采用了粒子系统、渐变效果、动态光源等技术,以及优化算法来提高渲染效率。

这个项目的意义在于,它不仅提供了一种环保、安全的跨年庆祝方式,同时也推动了Html5技术的发展,让更多的人了解到Canvas的强大功能。此外,通过这个项目,我们也希望能够激发更多人对于科技与艺术的结合,以及创新思维的探索。

目录结构

跨年烟花-Html5实现_附完整源码【可直接运行】_第1张图片
在这里插入图片描述
moon.png如下:
跨年烟花-Html5实现_附完整源码【可直接运行】_第2张图片
city.png如下
在这里插入图片描述

⚫完整源码

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
	<style>
		body{margin:0;padding:0;overflow: hidden;}
		.city{width:100%;position:fixed;bottom: 0px;z-index: 100;}
		.city img{width: 100%;}
	style>
	<title>html5夜景放烟花绽放动画效果title>
head>
<body onselectstart = "return false">

<div style="height:700px;overflow:hidden;">

	<canvas id='cas' style="background-color:rgba(0,5,24,1);">浏览器不支持canvascanvas>
	<div class="city"><img src="img/city.png" alt="" />div>
	<img src="img/moon.png" alt="" id="moon" style="visibility: hidden;"/>
	<div style="display:none">
		<div class="shape">新年快乐div>
		<div class="shape">合家幸福div>
        <div class="shape">万事如意div>
        <div class="shape">心想事成div>
        <div class="shape">财源广进div>
	div>
	
div>
	
	<script>
		var canvas = document.getElementById("cas");
		var ocas = document.createElement("canvas");
		var octx = ocas.getContext("2d");
		var ctx = canvas.getContext("2d");
		ocas.width = canvas.width = window.innerWidth;
		ocas.height = canvas.height = 700;
		var bigbooms = [];
	
		window.onload = function(){
			initAnimate()
		}

		function initAnimate(){
			drawBg();

			lastTime = new Date();
			animate();
		}

		var lastTime;
		function animate(){
			ctx.save();
			ctx.fillStyle = "rgba(0,5,24,0.1)";
			ctx.fillRect(0,0,canvas.width,canvas.height);
			ctx.restore();


			var newTime = new Date();
            if(newTime-lastTime>250+(window.innerHeight-767)/2){
				var random = Math.random()*100>2?true:false;
				var x = getRandom(canvas.width/5 , canvas.width*4/5);
				var y = getRandom(50 , 200);
				if(random){
					var bigboom = new Boom(getRandom(canvas.width/3,canvas.width*2/3) ,2,"#FFF" , {x:x , y:y});
					bigbooms.push(bigboom)
				}
				else {
					var bigboom = new Boom(getRandom(canvas.width/3,canvas.width*2/3) ,2,"#FFF" , {x:canvas.width/2 , y:200} , document.querySelectorAll(".shape")[parseInt(getRandom(0, document.querySelectorAll(".shape").length))]);
					bigbooms.push(bigboom)
				}
				lastTime = newTime;
				console.log(bigbooms)
			}

			stars.foreach(function(){
				this.paint();
			})

			drawMoon();

			bigbooms.foreach(function(index){
				var that = this;
				if(!this.dead){
					this._move();
					this._drawLight();
				}
				else{
					this.booms.foreach(function(index){
						if(!this.dead) {
							this.moveTo(index);
						}
						else if(index === that.booms.length-1){
							bigbooms[bigbooms.indexOf(that)] = null;
						}
					})
				}
			});
			
			raf(animate);
		}

		function drawMoon(){
			var moon = document.getElementById("moon");
			var centerX = canvas.width-200 , centerY = 100 , width = 80;
			if(moon.complete){
				ctx.drawImage(moon , centerX , centerY , width , width )
			}
			else {
				moon.onload = function(){
					ctx.drawImage(moon ,centerX , centerY , width , width)
				}
			}
			var index = 0;
			for(var i=0;i<10;i++){
				ctx.save();
				ctx.beginPath();
				ctx.arc(centerX+width/2 , centerY+width/2 , width/2+index , 0 , 2*Math.PI);
				ctx.fillStyle="rgba(240,219,120,0.005)";
				index+=2;
				ctx.fill();
				ctx.restore();
			}
			
		}

		Array.prototype.foreach = function(callback){
			for(var i=0;i<this.length;i++){
				if(this[i]!==null) callback.apply(this[i] , [i])
			}
		}

		var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); };
 		
		canvas.onclick = function(){
			var x = event.clientX;
			var y = event.clientY;
			var bigboom = new Boom(getRandom(canvas.width/3,canvas.width*2/3) ,2,"#FFF" , {x:x , y:y});
			bigbooms.push(bigboom)
		}

		// canvas.addEventLisener("touchstart" , function(event){
		// 	var touch = event.targetTouches[0];
		// 	var x = event.pageX;
		// 	var y = event.pageY;
		// 	var bigboom = new Boom(getRandom(canvas.width/3,canvas.width*2/3) ,2,"#FFF" , {x:x , y:y});
		// 	bigbooms.push(bigboom)
		// })

		var Boom = function(x,r,c,boomArea,shape){
			this.booms = [];
			this.x = x;
			this.y = (canvas.height+r);
			this.r = r;
			this.c = c;
			this.shape = shape || false;
			this.boomArea = boomArea;
			this.theta = 0;
			this.dead = false;
			this.ba = parseInt(getRandom(80 , 200));
		}
		Boom.prototype = {
			_paint:function(){
				ctx.save();
				ctx.beginPath();
				ctx.arc(this.x,this.y,this.r,0,2*Math.PI);
				ctx.fillStyle = this.c;
				ctx.fill();
				ctx.restore();
			},
			_move:function(){
				var dx = this.boomArea.x - this.x , dy = this.boomArea.y - this.y;
				this.x = this.x+dx*0.01;
				this.y = this.y+dy*0.01;

				if(Math.abs(dx)<=this.ba && Math.abs(dy)<=this.ba){
					if(this.shape){
						this._shapBoom();
					}
					else this._boom();
					this.dead = true;
				}
				else {
					this._paint();
				}
			},
			_drawLight:function(){
				ctx.save();
				ctx.fillStyle = "rgba(255,228,150,0.3)";
				ctx.beginPath();
				ctx.arc(this.x , this.y , this.r+3*Math.random()+1 , 0 , 2*Math.PI);
				ctx.fill();
				ctx.restore();
			},
			_boom:function(){
				var fragNum = getRandom(30 , 200);
				var style = getRandom(0,10)>=5? 1 : 2;
				var color;
				if(style===1){
					color = {
						a:parseInt(getRandom(128,255)),
						b:parseInt(getRandom(128,255)),
						c:parseInt(getRandom(128,255))
					}
				}

				var fanwei = parseInt(getRandom(300, 400));
				for(var i=0;i<fragNum;i++){
					if(style===2){
						color = {
							a:parseInt(getRandom(128,255)),
							b:parseInt(getRandom(128,255)),
							c:parseInt(getRandom(128,255))
						}
					}
					var a = getRandom(-Math.PI, Math.PI);
					var x = getRandom(0, fanwei) * Math.cos(a) + this.x;
					var y = getRandom(0, fanwei) * Math.sin(a) + this.y; 
					var radius = getRandom(0 , 2)
					var frag = new Frag(this.x , this.y , radius , color , x , y );
					this.booms.push(frag);
				}
			},
			_shapBoom:function(){
				var that = this;
				putValue(ocas , octx , this.shape , 5, function(dots){
					var dx = canvas.width/2-that.x;
					var dy = canvas.height/2-that.y;
					for(var i=0;i<dots.length;i++){
						color = {a:dots[i].a,b:dots[i].b,c:dots[i].c}
						var x = dots[i].x;
						var y = dots[i].y;
						var radius = 1;
						var frag = new Frag(that.x , that.y , radius , color , x-dx , y-dy);
						that.booms.push(frag);
					}
				})
			}
		}

		function putValue(canvas , context , ele , dr , callback){
			context.clearRect(0,0,canvas.width,canvas.height);
			var img = new Image();
			if(ele.innerHTML.indexOf("img")>=0){
				img.src = ele.getElementsByTagName("img")[0].src;
				imgload(img , function(){
					context.drawImage(img , canvas.width/2 - img.width/2 , canvas.height/2 - img.width/2);
					dots = getimgData(canvas , context , dr);
					callback(dots);
				})
			}
			else {
				var text = ele.innerHTML;
				context.save();
				var fontSize =200;
				context.font = fontSize+"px 宋体 bold";
				context.textAlign = "center";
				context.textBaseline = "middle";
				context.fillStyle = "rgba("+parseInt(getRandom(128,255))+","+parseInt(getRandom(128,255))+","+parseInt(getRandom(128,255))+" , 1)";
				context.fillText(text , canvas.width/2 , canvas.height/2);
				context.restore();
				dots = getimgData(canvas , context , dr);
				callback(dots);
			}
		}

		function imgload(img , callback){
			if(img.complete){
				callback.call(img);
			}
			else {
				img.onload = function(){
					callback.call(this);
				}
			}
		}

		function getimgData(canvas , context , dr){
			var imgData = context.getImageData(0,0,canvas.width , canvas.height);
			context.clearRect(0,0,canvas.width , canvas.height);
			var dots = [];
			for(var x=0;x<imgData.width;x+=dr){
				for(var y=0;y<imgData.height;y+=dr){
					var i = (y*imgData.width + x)*4;
					if(imgData.data[i+3] > 128){
						var dot = {x:x , y:y , a:imgData.data[i] , b:imgData.data[i+1] , c:imgData.data[i+2]};
						dots.push(dot);
					}
				}
			}
			return dots;
		}

		function getRandom(a , b){
			return Math.random()*(b-a)+a;
		}


		var maxRadius = 1 , stars=[];
		function drawBg(){
			for(var i=0;i<100;i++){
				var r = Math.random()*maxRadius;
				var x = Math.random()*canvas.width;
				var y = Math.random()*2*canvas.height - canvas.height;
				var star = new Star(x , y , r);
				stars.push(star);
				star.paint()
			}

		}

		var Star = function(x,y,r){
			this.x = x;this.y=y;this.r=r;
		}
		Star.prototype = {
			paint:function(){
				ctx.save();
				ctx.beginPath();
				ctx.arc(this.x , this.y , this.r , 0 , 2*Math.PI);
				ctx.fillStyle = "rgba(255,255,255,"+this.r+")";
				ctx.fill();
				ctx.restore();
			}
		}

		var focallength = 250;
		var Frag = function(centerX , centerY , radius , color ,tx , ty){
			this.tx = tx;
			this.ty = ty;
			this.x = centerX;
			this.y = centerY;
			this.dead = false;
			this.centerX = centerX;
			this.centerY = centerY;
			this.radius = radius;
			this.color = color;
		}

		Frag.prototype = {
			paint:function(){
				ctx.save();
				ctx.beginPath();
				ctx.arc(this.x , this.y , this.radius , 0 , 2*Math.PI);
				ctx.fillStyle = "rgba("+this.color.a+","+this.color.b+","+this.color.c+",1)";
				ctx.fill()
				ctx.restore();
			},
			moveTo:function(index){
				this.ty = this.ty+0.3;
				var dx = this.tx - this.x , dy = this.ty - this.y;
				this.x = Math.abs(dx)<0.1 ? this.tx : (this.x+dx*0.1);
				this.y = Math.abs(dy)<0.1 ? this.ty : (this.y+dy*0.1);
				if(dx===0 && Math.abs(dy)<=80){
					this.dead = true;
				}
				this.paint();
			}
		}
	script>

body>
html>

源码分析

这段代码实现了一个HTML页面,通过Canvas和JavaScript实现了一个夜景放烟花的动画效果。以下是对代码的主要分析:

  1. HTML结构:

    • :文档类型声明,指定使用XHTML 1.0 Transitional规范。
    • :HTML文档的根元素,指定了XML命名空间和语言(en)。
    • :文档的头部,包含元信息和样式表。
    • :设置字符集为UTF-8。