春節將至,喜慶的煙花安排上(js實現煙花)

jimyking發表於2022-01-22

一年一度的春節即將來臨,然後苦逼的我還在使勁的摸魚,未能回家體驗小時候路邊放爆竹的快樂時光,所以只能在網上來實現這個小小的心願了。煙花靜態效果圖如下:

為了大夥複製方便就不分開寫,直接複製即可,具體實現程式碼如下所示:

<!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>

提前給大家拜個早年了,虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威

相關文章