春节将至,喜庆的烟花安排上(js实现烟花)

一年一度的春节即将来临,然后苦逼的我还在使劲的摸鱼,未能回家体验小时候路边放爆竹的快乐时光,所以只能在网上来实现这个小小的心愿了。烟花静态效果图如下:

为了大伙复制方便就不分开写,直接复制即可,具体实现代码如下所示:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			body {
			  background-image: linear-gradient(6deg, #214, #000);
			  background-size: 100% 100%;overflow: hidden
			}
			
			canvas { display: block; }
		</style>
	</head>
	<body>
		<div></div>
		<script type="text/javascript">
			class Vector2 {
			  constructor(x = 0, y = 0) {
			    this.x = x;
			    this.y = y;
			  }
			
			  add(v) {
			    this.x += v.x;
			    this.y += v.y;
			    return this;
			  }
			
			  multiplyScalar(s) {
			    this.x *= s;
			    this.y *= s;
			    return this;
			  }
			
			  clone() {
			    return new Vector2(this.x, this.y);
			  }}
			
			
			class Time {
			  constructor() {
			    const now = Time.now();
			
			    this.delta = 0;
			    this.elapsed = 0;
			    this.start = now;
			    this.previous = now;
			  }
			
			  update() {
			    const now = Time.now();
			
			    this.delta = now - this.previous;
			    this.elapsed = now - this.start;
			    this.previous = now;
			  }
			
			  static now() {
			    return Date.now() / 1000;
			  }}
			
			
			class Particle {
			  constructor(position, velocity = new Vector2(), color = 'white', radius = 1, lifetime = 1, mass = 1) {
			    this.position = position;
			    this.velocity = velocity;
			    this.color = color;
			    this.radius = radius;
			    this.lifetime = lifetime;
			    this.mass = mass;
			
			    this.isInCanvas = true;
			    this.createdOn = Time.now();
			  }
			
			  update(time) {
			    if (!this.getRemainingLifetime()) {
			      return;
			    }
			
			    this.velocity.add(Particle.GRAVITATION.clone().multiplyScalar(this.mass));
			    this.position.add(this.velocity.clone().multiplyScalar(time.delta));
			  }
			
			  render(canvas, context) {
			    const remainingLifetime = this.getRemainingLifetime();
			
			    if (!remainingLifetime) return;
			
			    const radius = this.radius * remainingLifetime;
			
			    context.globalAlpha = remainingLifetime;
			    context.globalCompositeOperation = 'lighter';
			    context.fillStyle = this.color;
			
			    context.beginPath();
			    context.arc(this.position.x, this.position.y, radius, 0, Math.PI * 2);
			    context.fill();
			  }
			
			  getRemainingLifetime() {
			    const elapsedLifetime = Time.now() - this.createdOn;
			    return Math.max(0, this.lifetime - elapsedLifetime) / this.lifetime;
			  }}
			
			
			Particle.GRAVITATION = new Vector2(0, 9.81);
			
			class Trail extends Particle {
			  constructor(childFactory, position, velocity = new Vector2(), lifetime = 1, mass = 1) {
			    super(position, velocity);
			
			    this.childFactory = childFactory;
			    this.children = [];
			    this.lifetime = lifetime;
			    this.mass = mass;
			
			    this.isAlive = true;
			  }
			
			  update(time) {
			    super.update(time);
			
			    // Add a new child on every frame
			    if (this.isAlive && this.getRemainingLifetime()) {
			      this.children.push(this.childFactory(this));
			    }
			
			    // Remove particles that are dead
			    this.children = this.children.filter(function (child) {
			      if (child instanceof Trail) {
			        return child.isAlive;
			      }
			
			      return child.getRemainingLifetime();
			    });
			
			    // Kill trail if all particles fade away
			    if (!this.children.length) {
			      this.isAlive = false;
			    }
			
			    // Update particles
			    this.children.forEach(function (child) {
			      child.update(time);
			    });
			  }
			
			  render(canvas, context) {
			    // Render all children
			    this.children.forEach(function (child) {
			      child.render(canvas, context);
			    });
			  }}
			
			
			class Rocket extends Trail {
			  constructor(childFactory, explosionFactory, position, velocity = new Vector2()) {
			    super(childFactory, position, velocity);
			
			    this.explosionFactory = explosionFactory;
			    this.lifetime = 10;
			  }
			
			  update(time) {
			    if (this.getRemainingLifetime() && this.velocity.y > 0) {
			      this.explosionFactory(this);
			      this.lifetime = 0;
			    }
			
			    super.update(time);
			  }}
			
			
			const canvas = document.createElement('canvas');
			const context = canvas.getContext('2d');
			const time = new Time();
			let rockets = [];
			
			const getTrustParticleFactory = function (baseHue) {
			  function getColor() {
			    const hue = Math.floor(Math.random() * 15 + 30);
			    return `hsl(${hue}, 100%, 75%`;
			  }
			
			  return function (parent) {
			    const position = this.position.clone();
			    const velocity = this.velocity.clone().multiplyScalar(-.1);
			    velocity.x += (Math.random() - .5) * 8;
			    const color = getColor();
			    const radius = 1 + Math.random();
			    const lifetime = .5 + Math.random() * .5;
			    const mass = .01;
			
			    return new Particle(position, velocity, color, radius, lifetime, mass);
			  };
			};
			
			const getExplosionFactory = function (baseHue) {
			  function getColor() {
			    const hue = Math.floor(baseHue + Math.random() * 15) % 360;
			    const lightness = Math.floor(Math.pow(Math.random(), 2) * 50 + 50);
			    return `hsl(${hue}, 100%, ${lightness}%`;
			  }
			
			  function getChildFactory() {
			    return function (parent) {
			      const direction = Math.random() * Math.PI * 2;
			      const force = 8;
			      const velocity = new Vector2(Math.cos(direction) * force, Math.sin(direction) * force);
			      const color = getColor();
			      const radius = 1 + Math.random();
			      const lifetime = 1;
			      const mass = .1;
			
			      return new Particle(parent.position.clone(), velocity, color, radius, lifetime, mass);
			    };
			  }
			
			  function getTrail(position) {
			    const direction = Math.random() * Math.PI * 2;
			    const force = Math.random() * 128;
			    const velocity = new Vector2(Math.cos(direction) * force, Math.sin(direction) * force);
			    const lifetime = .5 + Math.random();
			    const mass = .075;
			
			    return new Trail(getChildFactory(), position, velocity, lifetime, mass);
			  }
			
			  return function (parent) {
			    let trails = 32;
			    while (trails--) {
			      parent.children.push(getTrail(parent.position.clone()));
			    }
			  };
			};
			
			const addRocket = function () {
			  const trustParticleFactory = getTrustParticleFactory();
			  const explosionFactory = getExplosionFactory(Math.random() * 360);
			
			  const position = new Vector2(Math.random() * canvas.width, canvas.height);
			  const thrust = window.innerHeight * .75;
			  const angle = Math.PI / -2 + (Math.random() - .5) * Math.PI / 8;
			  const velocity = new Vector2(Math.cos(angle) * thrust, Math.sin(angle) * thrust);
			  const lifetime = 3;
			
			  rockets.push(new Rocket(trustParticleFactory, explosionFactory, position, velocity, lifetime));
			
			  rockets = rockets.filter(function (rocket) {
			    return rocket.isAlive;
			  });
			};
			
			const render = function () {
			  requestAnimationFrame(render);
			
			  time.update();
			  context.clearRect(0, 0, canvas.width, canvas.height);
			
			  rockets.forEach(function (rocket) {
			    rocket.update(time);
			    rocket.render(canvas, context);
			  });
			};
			
			const resize = function () {
			  canvas.height = window.innerHeight;
			  canvas.width = window.innerWidth;
			};
			
			canvas.onclick = addRocket;
			document.body.appendChild(canvas);
			
			window.onresize = resize;
			resize();
			
			setInterval(addRocket, 2000);
			render();
		</script>
	</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值