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



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

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

提前给大家拜个早年了,虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威虎虎生威

最新文章

  1. 树分治 poj 1741
  2. 基于CCS3.3平台搭建DSP/BIOS系统
  3. pecl install imagick
  4. 数据结构Java实现05----栈:顺序栈和链式堆栈
  5. Spring的核心机制&mdash;&mdash;依赖注入(Dependency Inject)
  6. Android service binder aidl 关系
  7. TabHost 两种使用方法 直接让一个Activity 继承TabActivity 和 利用findViwById()方法取得TagHost组件
  8. poj 2773 利用欧拉函数求互质数
  9. 如何从Linux系统中获取带宽、流量网络数据
  10. Java多线程之synchronized(五)
  11. idea + mybatis generator + maven 插件使用
  12. zabbix灵活使用userparameters
  13. UART知识总结
  14. ConcurrentHashMap基于JDK1.8源码剖析
  15. 持续集成①安装部署jenkins从git获取代码
  16. 发布-订阅消息系统Kafka简介
  17. svn插件下载的两种方式
  18. Warm up HDU - 4612( 树的直径 边双连通分量)
  19. 实用ExtJS教程100例-006:ExtJS中Window的用法示例
  20. c++ remove_if

热门文章

  1. mysql添加上log_bin步骤如下
  2. 优雅的按键模块-----Multi-button
  3. Elasticsearch 和 solr 的区别
  4. windows10 下使用 spdlog 总结(spdlog 1.7)
  5. c++11之日期和时间库
  6. 【LeetCode】1128. Number of Equivalent Domino Pairs 等价多米诺骨牌对的数量(Python)
  7. Codeforces 567B:Berland National Library(模拟)
  8. 想看Vue文档,cn放错位置,误入xx网站...
  9. Elasticsearch(二)--集群原理及优化
  10. Cube 技术解读 | Cube 小程序技术详解