不同语言编写的绚丽烟花
简单Html先来一个简单的形象实现烟花(绝对绚丽)
先看效果
源码
<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>html5 canvas除夕烟花</title><base target="_blank"/><link rel="stylesheet" type="text/css" href="http://hovertree.com/texiao/html5/43/css/normalize.css"/><link rel="stylesheet" type="text/css" href="http://hovertree.com/texiao/html5/43/css/hovertree.css"></head><body><div class="hovertree"></div><script type="text/javascript" src="http://down.hovertree.com/jquery/jquery-1.11.0.min.js"></script><script type="text/javascript" src="http://hovertree.com/texiao/html5/43/js/jquery.fireworks.js"></script><script type="text/javascript">$('.hovertree').fireworks({
sound:true,// sound effect
opacity:0.9,
width:'100%',
height:'100%'});</script><div style="width:340px;position:fixed;z-index:99;"><a href="http://hovertree.com/"></a><a href="http://hovertree.com/h/bjag/me34x8fk.htm"></a></div></body></html>
HTML+Canvas(内含js)
我们先看实现效果
源码如下,一共三百多行
<!doctype html><html><head><meta charset="utf-8"><title>除夕炫彩</title><style>
html,body{
margin:0px;
width:100%;
height:100%;
overflow:hidden;
background:#000;}</style></head><body><canvas id="canvas" style="position:absolute;width:100%;height:100%;z-index:8888"></canvas><canvas style="position:absolute;width:100%;height:100%;z-index:9999"class="canvas"></canvas><div class="overlay"><div class="tabs"><div class="tabs-labels"><span class="tabs-label">Commands</span><span class="tabs-label">Info</span><span class="tabs-label">Share</span></div><div class="tabs-panels"><ul class="tabs-panel commands"></ul></div></div></div><script>functioninitVars(){
pi=Math.PI;
ctx=canvas.getContext("2d");
canvas.width=canvas.clientWidth;
canvas.height=canvas.clientHeight;
cx=canvas.width/2;
cy=canvas.height/2;
playerZ=-25;
playerX=playerY=playerVX=playerVY=playerVZ=pitch=yaw=pitchV=yawV=0;
scale=600;
seedTimer=0;seedInterval=5,seedLife=100;gravity=.02;
seeds=newArray();
sparkPics=newArray();
s="https://cantelope.org/NYE/";for(i=1;i<=10;++i){
sparkPic=newImage();
sparkPic.src=s+"spark"+i+".png";
sparkPics.push(sparkPic);}
sparks=newArray();
pow1=newAudio(s+"pow1.ogg");
pow2=newAudio(s+"pow2.ogg");
pow3=newAudio(s+"pow3.ogg");
pow4=newAudio(s+"pow4.ogg");
frames =0;}functionrasterizePoint(x,y,z){var p,d;
x-=playerX;
y-=playerY;
z-=playerZ;
p=Math.atan2(x,z);
d=Math.sqrt(x*x+z*z);
x=Math.sin(p-yaw)*d;
z=Math.cos(p-yaw)*d;
p=Math.atan2(y,z);
d=Math.sqrt(y*y+z*z);
y=Math.sin(p-pitch)*d;
z=Math.cos(p-pitch)*d;var rx1=-1000,ry1=1,rx2=1000,ry2=1,rx3=0,ry3=0,rx4=x,ry4=z,uc=(ry4-ry3)*(rx2-rx1)-(rx4-rx3)*(ry2-ry1);if(!uc)return{x:0,y:0,d:-1};var ua=((rx4-rx3)*(ry1-ry3)-(ry4-ry3)*(rx1-rx3))/uc;var ub=((rx2-rx1)*(ry1-ry3)-(ry2-ry1)*(rx1-rx3))/uc;if(!z)z=.000000001;if(ua>0&&ua<1&&ub>0&&ub<1){return{
x:cx+(rx1+ua*(rx2-rx1))*scale,
y:cy+y/z*scale,
d:Math.sqrt(x*x+y*y+z*z)};}else{return{
x:cx+(rx1+ua*(rx2-rx1))*scale,
y:cy+y/z*scale,
d:-1};}}functionspawnSeed(){
seed=newObject();
seed.x=-50+Math.random()*100;
seed.y=25;
seed.z=-50+Math.random()*100;
seed.vx=.1-Math.random()*.2;
seed.vy=-1.5;//*(1+Math.random()/2);
seed.vz=.1-Math.random()*.2;
seed.born=frames;
seeds.push(seed);}functionsplode(x,y,z){
t=5+parseInt(Math.random()*150);
sparkV=1+Math.random()*2.5;
type=parseInt(Math.random()*3);switch(type){case0:
pic1=parseInt(Math.random()*10);break;case1:
pic1=parseInt(Math.random()*10);do{ pic2=parseInt(Math.random()*10);}while(pic2==pic1);break;case2:
pic1=parseInt(Math.random()*10);do{ pic2=parseInt(Math.random()*10);}while(pic2==pic1);do{ pic3=parseInt(Math.random()*10);}while(pic3==pic1 || pic3==pic2);break;}for(m=1;m<t;++m){
spark=newObject();
spark.x=x; spark.y=y; spark.z=z;
p1=pi*2*Math.random();
p2=pi*Math.random();
v=sparkV*(1+Math.random()/6)
spark.vx=Math.sin(p1)*Math.sin(p2)*v;
spark.vz=Math.cos(p1)*Math.sin(p2)*v;
spark.vy=Math.cos(p2)*v;switch(type){case0: spark.img=sparkPics[pic1];break;case1:
spark.img=sparkPics[parseInt(Math.random()*2)?pic1:pic2];break;case2:switch(parseInt(Math.random()*3)){case0: spark.img=sparkPics[pic1];break;case1: spark.img=sparkPics[pic2];break;case2: spark.img=sparkPics[pic3];break;}break;}
spark.radius=25+Math.random()*50;
spark.alpha=1;
spark.trail=newArray();
sparks.push(spark);}switch(parseInt(Math.random()*4)){case0: pow=newAudio(s+"pow1.ogg");break;case1: pow=newAudio(s+"pow2.ogg");break;case2: pow=newAudio(s+"pow3.ogg");break;case3: pow=newAudio(s+"pow4.ogg");break;}
d=Math.sqrt((x-playerX)*(x-playerX)+(y-playerY)*(y-playerY)+(z-playerZ)*(z-playerZ));
pow.volume=1.5/(1+d/10);
pow.play();}functiondoLogic(){if(seedTimer<frames){
seedTimer=frames+seedInterval*Math.random()*10;spawnSeed();}for(i=0;i<seeds.length;++i){
seeds[i].vy+=gravity;
seeds[i].x+=seeds[i].vx;
seeds[i].y+=seeds[i].vy;
seeds[i].z+=seeds[i].vz;if(frames-seeds[i].born>seedLife){splode(seeds[i].x,seeds[i].y,seeds[i].z);
seeds.splice(i,1);}}for(i=0;i<sparks.length;++i){if(sparks[i].alpha>0&& sparks[i].radius>5){
sparks[i].alpha-=.01;
sparks[i].radius/=1.02;
sparks[i].vy+=gravity;
point=newObject();
point.x=sparks[i].x;
point.y=sparks[i].y;
point.z=sparks[i].z;if(sparks[i].trail.length){
x=sparks[i].trail[sparks[i].trail.length-1].x;
y=sparks[i].trail[sparks[i].trail.length-1].y;
z=sparks[i].trail[sparks[i].trail.length-1].z;
d=((point.x-x)*(point.x-x)+(point.y-y)*(point.y-y)+(point.z-z)*(point.z-z));if(d>9){
sparks[i].trail.push(point);}}else{
sparks[i].trail.push(point);}if(sparks[i].trail.length>5)sparks[i].trail.splice(0,1);
sparks[i].x+=sparks[i].vx;
sparks[i].y+=sparks[i].vy;
sparks[i].z+=sparks[i].vz;
sparks[i].vx/=1.075;
sparks[i].vy/=1.075;
sparks[i].vz/=1.075;}else{
sparks.splice(i,1);}}
p=Math.atan2(playerX,playerZ);
d=Math.sqrt(playerX*playerX+playerZ*playerZ);
d+=Math.sin(frames/80)/1.25;
t=Math.sin(frames/200)/40;
playerX=Math.sin(p+t)*d;
playerZ=Math.cos(p+t)*d;
yaw=pi+p+t;}functionrgb(col){var r =parseInt((.5+Math.sin(col)*.5)*16);var g =parseInt((.5+Math.cos(col)*.5)*16);var b =parseInt((.5-Math.sin(col)*.5)*16);return"#"+r.toString(16)+g.toString(16)+b.toString(16);}functiondraw(){
ctx.clearRect(0,0,cx*2,cy*2);
ctx.fillStyle="#ff8";for(i=-100;i<100;i+=3){for(j=-100;j<100;j+=4){
x=i;z=j;y=25;
point=rasterizePoint(x,y,z);if(point.d!=-1){
size=250/(1+point.d);
d = Math.sqrt(x * x + z * z);
a =0.75- Math.pow(d /100,6)*0.75;if(a>0){
ctx.globalAlpha = a;
ctx.fillRect(point.x-size/2,point.y-size/2,size,size);}}}}
ctx.globalAlpha=1;for(i=0;i<seeds.length;++i){
point=rasterizePoint(seeds[i].x,seeds[i].y,seeds[i].z);if(point.d!=-1){
size=200/(1+point.d);
ctx.fillRect(point.x-size/2,point.y-size/2,size,size);}}
point1=newObject();for(i=0;i<sparks.length;++i){
point=rasterizePoint(sparks[i].x,sparks[i].y,sparks[i].z);if(point.d!=-1){
size=sparks[i].radius*200/(1+point.d);if(sparks[i].alpha<0)sparks[i].alpha=0;if(sparks[i].trail.length){
point1.x=point.x;
point1.y=point.y;switch(sparks[i].img){case sparkPics[0]:ctx.strokeStyle="#f84";break;case sparkPics[1]:ctx.strokeStyle="#84f";break;case sparkPics[2]:ctx.strokeStyle="#8ff";break;case sparkPics[3]:ctx.strokeStyle="#fff";break;case sparkPics[4]:ctx.strokeStyle="#4f8";break;case sparkPics[5]:ctx.strokeStyle="#f44";break;case sparkPics[6]:ctx.strokeStyle="#f84";break;case sparkPics[7]:ctx.strokeStyle="#84f";break;case sparkPics[8]:ctx.strokeStyle="#fff";break;case sparkPics[9]:ctx.strokeStyle="#44f";break;}for(j=sparks[i].trail.length-1;j>=0;--j){
point2=rasterizePoint(sparks[i].trail[j].x,sparks[i].trail[j].y,sparks[i].trail[j].z);if(point2.d!=-1){
ctx.globalAlpha=j/sparks[i].trail.length*sparks[i].alpha/2;
ctx.beginPath();
ctx.moveTo(point1.x,point1.y);
ctx.lineWidth=1+sparks[i].radius*10/(sparks[i].trail.length-j)/(1+point2.d);
ctx.lineTo(point2.x,point2.y);
ctx.stroke();
point1.x=point2.x;
point1.y=point2.y;}}}
ctx.globalAlpha=sparks[i].alpha;
ctx.drawImage(sparks[i].img,point.x-size/2,point.y-size/2,size,size);}}}functionframe(){if(frames>100000){
seedTimer=0;
frames=0;}
frames++;draw();doLogic();requestAnimationFrame(frame);}
window.addEventListener("resize",()=>{
canvas.width=canvas.clientWidth;
canvas.height=canvas.clientHeight;
cx=canvas.width/2;
cy=canvas.height/2;});initVars();frame();</script><script src="js/index.js"></script></body></html>
下面是引用的js源码,js渲染需要比较多的代码。
varS={init:function(){var action = window.location.href,
i = action.indexOf('?a=');S.Drawing.init('.canvas');
document.body.classList.add('body--ready');if(i !==-1){S.UI.simulate(decodeURI(action).substring(i +3));}else{S.UI.simulate('除夕节日快乐');}S.Drawing.loop(function(){S.Shape.render();});}};S.Drawing =(function(){var canvas,
context,
renderFn
requestFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||function(callback){
window.setTimeout(callback,1000/60);};return{init:function(el){
canvas = document.querySelector(el);
context = canvas.getContext('2d');this.adjustCanvas();
window.addEventListener('resize',function(e){S.Drawing.adjustCanvas();});},loop:function(fn){
renderFn =!renderFn ? fn : renderFn;this.clearFrame();renderFn();requestFrame.call(window,this.loop.bind(this));},adjustCanvas:function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;},clearFrame:function(){
context.clearRect(0,0, canvas.width, canvas.height);},getArea:function(){return{ w: canvas.width, h: canvas.height };},drawCircle:function(p, c){
context.fillStyle = c.render();
context.beginPath();
context.arc(p.x, p.y, p.z,0,2* Math.PI,true);
context.closePath();
context.fill();}}}());S.UI=(function(){var canvas = document.querySelector('.canvas'),
interval,
isTouch =false,//('ontouchstart' in window || navigator.msMaxTouchPoints),
currentAction,
resizeTimer,
time,
maxShapeSize =30,
firstAction =true,
sequence =[],
cmd ='#';functionformatTime(date){var h = date.getHours(),
m = date.getMinutes(),
m = m <10?'0'+ m : m;return h +':'+ m;}functiongetValue(value){return value && value.split(' ')[1];}functiongetAction(value){
value = value && value.split(' ')[0];return value && value[0]=== cmd && value.substring(1);}functiontimedAction(fn, delay, max, reverse){clearInterval(interval);
currentAction = reverse ? max :1;fn(currentAction);if(!max ||(!reverse && currentAction < max)||(reverse && currentAction >0)){
interval =setInterval(function(){
currentAction = reverse ? currentAction -1: currentAction +1;fn(currentAction);if((!reverse && max && currentAction === max)||(reverse && currentAction ===0)){clearInterval(interval);}}, delay);}}functionreset(destroy){clearInterval(interval);
sequence =[];
time =null;
destroy &&S.Shape.switchShape(S.ShapeBuilder.letter(''));}functionperformAction(value){var action,
value,
current;// overlay.classList.remove('overlay--visible');
sequence =typeof(value)==='object'? value : sequence.concat(value.split('|'));// input.value = '';// checkInputWidth();timedAction(function(index){
current = sequence.shift();
action =getAction(current);
value =getValue(current);switch(action){case'countdown':
value =parseInt(value)||10;
value = value >0? value :10;timedAction(function(index){if(index ===0){if(sequence.length ===0){S.Shape.switchShape(S.ShapeBuilder.letter(''));}else{performAction(sequence);}}else{S.Shape.switchShape(S.ShapeBuilder.letter(index),true);}},1000, value,true);break;case'rectangle':
value = value && value.split('x');
value =(value && value.length ===2)? value :[maxShapeSize, maxShapeSize /2];S.Shape.switchShape(S.ShapeBuilder.rectangle(Math.min(maxShapeSize,parseInt(value[0])), Math.min(maxShapeSize,parseInt(value[1]))));break;case'circle':
value =parseInt(value)|| maxShapeSize;
value = Math.min(value, maxShapeSize);S.Shape.switchShape(S.ShapeBuilder.circle(value));break;case'time':var t =formatTime(newDate());if(sequence.length >0){S.Shape.switchShape(S.ShapeBuilder.letter(t));}else{timedAction(function(){
t =formatTime(newDate());if(t !== time){
time = t;S.Shape.switchShape(S.ShapeBuilder.letter(time));}},1000);}break;default:S.Shape.switchShape(S.ShapeBuilder.letter(current[0]=== cmd ?'What?': current));}},2000, sequence.length);}functioncheckInputWidth(e){if(input.value.length >18){
ui.classList.add('ui--wide');}else{
ui.classList.remove('ui--wide');}if(firstAction && input.value.length >0){
ui.classList.add('ui--enter');}else{
ui.classList.remove('ui--enter');}}functionbindEvents(){
document.body.addEventListener('keydown',function(e){
input.focus();if(e.keyCode ===13){
firstAction =false;reset();performAction(input.value);}});
canvas.addEventListener('click',function(e){
overlay.classList.remove('overlay--visible');});}functioninit(){bindEvents();// input.focus();
isTouch && document.body.classList.add('touch');}// Initinit();return{simulate:function(action){performAction(action);}}}());S.UI.Tabs =(function(){var tabs = document.querySelector('.tabs'),
labels = document.querySelector('.tabs-labels'),
triggers = document.querySelectorAll('.tabs-label'),
panels = document.querySelectorAll('.tabs-panel');functionactivate(i){
triggers[i].classList.add('tabs-label--active');
panels[i].classList.add('tabs-panel--active');}functionbindEvents(){
labels.addEventListener('click',function(e){var el = e.target,
index;if(el.classList.contains('tabs-label')){for(var t =0; t < triggers.length; t++){
triggers[t].classList.remove('tabs-label--active');
panels[t].classList.remove('tabs-panel--active');if(el === triggers[t]){
index = t;}}activate(index);}});}functioninit(){activate(0);bindEvents();}// Initinit();}());S.Point=function(args){this.x = args.x;this.y = args.y;this.z = args.z;this.a = args.a;this.h = args.h;};S.Color=function(r, g, b, a){this.r = r;this.g = g;this.b = b;this.a = a;};S.Color.prototype ={render:function(){return'rgba('+this.r +','++this.g +','+this.b +','+this.a +')';}};S.Dot=function(x, y){this.p =newS.Point({
x: x,
y: y,
z:5,
a:1,
h:0});this.e =0.07;this.s =true;this.c =newS.Color(255,255,255,this.p.a);this.t =this.clone();this.q =[];};S.Dot.prototype ={clone:function(){returnnewS.Point({
x:this.x,
y:this.y,
z:this.z,
a:this.a,
h:this.h
});},_draw:function(){this.c.a =this.p.a;S.Drawing.drawCircle(this.p,this.c);},_moveTowards:function(n){var details =this.distanceTo(n,true),
dx = details[0],
dy = details[1],
d = details[2],
e =this.e * d;if(this.p.h ===-1){this.p.x = n.x;this.p.y = n.y;returntrue;}if(d >1){this.p.x -=((dx / d)* e);this.p.y -=((dy / d)* e);}else{if(this.p.h >0){this.p.h--;}else{returntrue;}}returnfalse;},_update:function(){if(this._moveTowards(this.t)){var p =this.q.shift();if(p){this.t.x = p.x ||this.p.x;this.t.y = p.y ||this.p.y;this.t.z = p.z ||this.p.z;this.t.a = p.a ||this.p.a;this.p.h = p.h ||0;}else{if(this.s){this.p.x -= Math.sin(Math.random()*3.142);this.p.y -= Math.sin(Math.random()*3.142);}else{this.move(newS.Point({
x:this.p.x +(Math.random()*50)-25,
y:this.p.y +(Math.random()*50)-25,}));}}}
d =this.p.a -this.t.a;this.p.a = Math.max(0.1,this.p.a -(d *0.05));
d =this.p.z -this.t.z;this.p.z = Math.max(1,this.p.z -(d *0.05));},distanceTo:function(n, details){var dx =this.p.x - n.x,
dy =this.p.y - n.y,
d = Math.sqrt(dx * dx + dy * dy);return details ?[dx, dy, d]: d;},move:function(p, avoidStatic){if(!avoidStatic ||(avoidStatic &&this.distanceTo(p)>1)){this.q.push(p);}},render:function(){this._update();this._draw();}}S.ShapeBuilder =(function(){var gap =13,
shapeCanvas = document.createElement('canvas'),
shapeContext = shapeCanvas.getContext('2d'),
fontSize =500,
fontFamily ='Avenir, Helvetica Neue, Helvetica, Arial, sans-serif';functionfit(){
shapeCanvas.width = Math.floor(window.innerWidth / gap)* gap;
shapeCanvas.height = Math.floor(window.innerHeight / gap)* gap;
shapeContext.fillStyle ='red';
shapeContext.textBaseline ='middle';
shapeContext.textAlign ='center';}functionprocessCanvas(){var pixels = shapeContext.getImageData(0,0, shapeCanvas.width, shapeCanvas.height).data;
dots =[],
pixels,
x =0,
y =0,
fx = shapeCanvas.width,
fy = shapeCanvas.height,
w =0,
h =0;for(var p =0; p < pixels.length; p +=(4* gap)){if(pixels[p +3]>0){
dots.push(newS.Point({
x: x,
y: y
}));
w = x > w ? x : w;
h = y > h ? y : h;
fx = x < fx ? x : fx;
fy = y < fy ? y : fy;}
x += gap;if(x >= shapeCanvas.width){
x =0;
y += gap;
p += gap *4* shapeCanvas.width;}}return{ dots: dots, w: w + fx, h: h + fy };}functionsetFontSize(s){
shapeContext.font ='bold '+ s +'px '+ fontFamily;}functionisNumber(n){return!isNaN(parseFloat(n))&&isFinite(n);}functioninit(){fit();
window.addEventListener('resize', fit);}// Initinit();return{imageFile:function(url, callback){var image =newImage(),
a =S.Drawing.getArea();
image.onload=function(){
shapeContext.clearRect(0,0, shapeCanvas.width, shapeCanvas.height);
shapeContext.drawImage(this,0,0, a.h *0.6, a.h *0.6);callback(processCanvas());};
image.onerror=function(){callback(S.ShapeBuilder.letter('What?'));}
image.src = url;},circle:function(d){var r = Math.max(0, d)/2;
shapeContext.clearRect(0,0, shapeCanvas.width, shapeCanvas.height);
shapeContext.beginPath();
shapeContext.arc(r * gap, r * gap, r * gap,0,2* Math.PI,false);
shapeContext.fill();
shapeContext.closePath();returnprocessCanvas();},letter:function(l){var s =0;setFontSize(fontSize);
s = Math.min(fontSize,(shapeCanvas.width / shapeContext.measureText(l).width)*0.8* fontSize,(shapeCanvas.height / fontSize)*(isNumber(l)?1:0.45)* fontSize);setFontSize(s);
shapeContext.clearRect(0,0, shapeCanvas.width, shapeCanvas.height);
shapeContext.fillText(l, shapeCanvas.width /2, shapeCanvas.height /2);returnprocessCanvas();},rectangle:function(w, h){var dots =[],
width = gap * w,
height = gap * h;for(var y =0; y < height; y += gap){for(var x =0; x < width; x += gap){
dots.push(newS.Point({
x: x,
y: y,}));}}return{ dots: dots, w: width, h: height };}};}());S.Shape =(function(){var dots =[],
width =0,
height =0,
cx =0,
cy =0;functioncompensate(){var a =S.Drawing.getArea();
cx = a.w /2- width /2;
cy = a.h /2- height /2;}return{shuffleIdle:function(){var a =S.Drawing.getArea();for(var d =0; d < dots.length; d++){if(!dots[d].s){
dots[d].move({
x: Math.random()* a.w,
y: Math.random()* a.h
});}}},switchShape:function(n, fast){var size,
a =S.Drawing.getArea();
width = n.w;
height = n.h;compensate();if(n.dots.length > dots.length){
size = n.dots.length - dots.length;for(var d =1; d <= size; d++){
dots.push(newS.Dot(a.w /2, a.h /2));}}var d =0,
i =0;while(n.dots.length >0){
i = Math.floor(Math.random()* n.dots.length);
dots[d].e = fast ?0.25:(dots[d].s ?0.14:0.11);if(dots[d].s){
dots[d].move(newS.Point({
z: Math.random()*20+10,
a: Math.random(),
h:18}));}else{
dots[d].move(newS.Point({
z: Math.random()*5+5,
h: fast ?18:30}));}
dots[d].s =true;
dots[d].move(newS.Point({
x: n.dots[i].x + cx,
y: n.dots[i].y + cy,
a:1,
z:5,
h:0}));
n.dots = n.dots.slice(0, i).concat(n.dots.slice(i +1));
d++;}for(var i = d; i < dots.length; i++){if(dots[i].s){
dots[i].move(newS.Point({
z: Math.random()*20+10,
a: Math.random(),
h:20}));
dots[i].s =false;
dots[i].e =0.04;
dots[i].move(newS.Point({
x: Math.random()* a.w,
y: Math.random()* a.h,
a:0.3,//.4
z: Math.random()*4,
h:0}));}}},render:function(){for(var d =0; d < dots.length; d++){
dots[d].render();}}}}());S.init();
如果你不希望有ui界面上的文字,要纯的烟花,可以在js文件中将 S.UI.simulate(‘除夕节日快乐’);进行注释。
js烟花效果
还是先看效果,录制的效果不太好,自己可以去尝试,也是非常好看的。
下面看源码,z这个比较简单,因为没有那么多渲染
<!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"><head><title>超炫网页烟花效果</title></head><style type="text/css">.fire{
display:block;
overflow:hidden;
font-size:12px;
position:absolute;}
body{
overflow:hidden;
background:#000;}
html{
overflow:hidden;
background:#000;}</style><body></body><script type="text/javascript">varFire=function(r, color){this.radius = r ||12;this.color = color;this.xpos =0;this.ypos =0;this.zpos =0;this.vx =0;this.vy =0;this.vz =0;this.mass =1;this.x =0;this.y=0;this.p = document.createElement("span");this.p.className ="fire";this.p.innerHTML ="*";this.p.style.fontSize =this.radius +"px";this.p.style.color ="#"+this.color;}Fire.prototype ={append:function(parent){
parent.appendChild(this.p);},setSize:function(scale){this.p.style.fontSize =this.radius * scale +"px";},setPosition:function(x, y){this.p.style.left = x +"px";this.p.style.top = y +"px";},setVisible:function(b){this.p.style.display = b ?"block":"none";}}varfireworks=function(){var fires =newArray();var count =150;var fl =250;var vpx =500;var vpy =300;var gravity =.5;var floor =200;var bounce =-.8;var timer;var wind =((Math.floor(Math.random()*3)+3)/10)*(Math.random()*2-1>0?1:-1)*.25;var wpos =0;var wcount;return{init:function(){
wcount =50+ Math.floor(Math.random()*100);for(var i=0; i<count; i++){var color =0xFF0000;
color =(Math.random()*0xFFFFFF).toString(16).toString().split(".")[0];while(color.length <6){
color ="0"+ color;}var fire =newFire(12, color);
fires.push(fire);
fire.ypos =-100;
fire.vz = Math.random()*6-3;
fire.vx =(Math.random()*2-1)*2;
fire.vy = Math.random()*-15-15;
fire.x =500
fire.y =600;
fire.append(document.body);}var that =this;
timer =setInterval(function(){
wpos++;if(wpos >= wcount){
wpos =0;
wcount =50+ Math.floor(Math.random()*100);
wind =((Math.floor(Math.random()*3)+3)/10)*(Math.random()*2-1>0?1:-1)*.25;}for(var i=0;i<count; i++){
that.move(fires[i]);}},30);},move:function(fire){
fire.vy += gravity;
fire.x += fire.vx;
fire.y += fire.vy;
fire.vx += wind;
fire.setPosition(fire.x, fire.y);if(fire.x <0|| fire.x >1000|| fire.y <0|| fire.y >600){
fire.vx =(Math.random()*2-1)*2;
fire.vy = Math.random()*-15-15;
fire.x =500;
fire.y =600;
fire.setPosition(fire.x, fire.y);}}}}fireworks().init();</script></html>
三 用python实现的烟花(可以选择背景)
还是先看效果
源码如下
main.py
import tkinter as tk
fromPILimport Image, ImageTk
from time import time, sleep
from random import choice, uniform, randint
from particle import Particle
# 颜色选项
colors =['red','blue','yellow','white','green','orange','purple','seagreen','indigo','cornflowerblue']HEIGHT=800WIDTH=1200
def simulate(cv):"""
循环调用保持不停
"""
t =time()
explode_points =[]
wait_time =randint(10,100)
numb_explode =randint(5,50)
# 创建一个所有粒子同时扩大的二维列表
for point inrange(numb_explode):
objects =[]
x_cordi =randint(0.05*WIDTH,0.95*WIDTH)
y_cordi =randint(0.05*HEIGHT,0.95*HEIGHT)
speed =uniform(0.2,2.)
size =uniform(0.2,3)
color =choice(colors)
explosion_speed =uniform(0.1,0.5)
explosion_radius =randint(5,15)
total_particles =randint(20,50)for i inrange(1, total_particles):
r =Particle(cv, idx=i, total=total_particles, explosion_speed=explosion_speed, explosion_radius=explosion_radius,
x=x_cordi, y=y_cordi, vx=speed, vy=speed, color=color, size=size, lifespan=abs(uniform(0.2,1.75)))
objects.append(r)
explode_points.append(objects)
total_time =.0
# 1.8s内一直扩大
while total_time <1.8:sleep(0.01)
tnew =time()
t, dt = tnew, tnew - t
for point in explode_points:for item in point:
item.update(dt)
cv.update()
total_time += dt
# 循环调用
root.after(wait_time, simulate, cv)
def close(*ignore):"""退出程序、关闭窗口"""
global root
root.quit()if __name__ =='__main__':
root = tk.Tk()
cv = tk.Canvas(root, height=HEIGHT, width=WIDTH)
image = Image.open("D:\\python\\pydoc\\pystudy\\project1\\fireworks-master\\__pycache__\\g.jpg")
photo = ImageTk.PhotoImage(image)
cv.create_image(0,0, image=photo, anchor='nw')
cv.pack()
root.protocol("WM_DELETE_WINDOW", close)
root.after(100, simulate, cv)
root.mainloop()
particle.py
from math import sin, cos, radians
# 模拟重力
GRAVITY=0.1classParticle(object):
def __init__(self, cv, idx, total, explosion_speed, explosion_radius=1, x=0., y=0., vx=0., vy=0., size=2., color='red', lifespan=2):"""
粒子在空中随机生成随机,变成一个圈、下坠、消失
属性:- id: 粒子的id
- x, y: 粒子的坐标
- vx, vy: 在坐标的变化速度
- total: 总数
- age: 粒子存在的时长
- color: 颜色
- cv: 画布
- lifespan: 最高存在时长
"""
self.id = idx
self.x = x
self.y = y
self.initial_speed = explosion_speed
self.explosion_radius = explosion_radius
self.vx = vx
self.vy = vy
self.total = total
self.age =0
self.color = color
self.cv = cv
self.cid = self.cv.create_oval(
x - size, y - size, x + size,
y + size, fill=self.color)
self.lifespan = lifespan
def update(self, dt):
self.age += dt
# 粒子范围扩大
if self.alive() and self.expand():
move_x =cos(radians(self.id *360/ self.total))* self.initial_speed
move_y =sin(radians(self.id *360/ self.total))* self.initial_speed
self.cv.move(self.cid, move_x * self.explosion_radius, move_y * self.explosion_radius)
self.vx = move_x /(float(dt)*1000)
# 以自由落体坠落
elif self.alive():
move_x =cos(radians(self.id *360/ self.total))
# we technically don't need to update x, y because move will do the job
self.cv.move(self.cid, self.vx + move_x, self.vy +GRAVITY* dt)
self.vy +=GRAVITY* dt
# 移除超过最高时长的粒子
elif self.cid is not None:
self.cv.delete(self.cid)
self.cid = None
# 扩大的时间
def expand(self):return self.age <=1.2
# 粒子是否在最高存在时长内
def alive(self):return self.age <= self.lifespan
然后自己存放一个放置图片的路径即可
版权归原作者 兰舟千帆 所有, 如有侵权,请联系我们删除。