- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- <style>
- html, body { margin: 0; height: 100%; } canvas { width: 100%; height:
- 100%; background: black; }
- </style>
- </head>
- <body>
- <canvas>
- </canvas>
- <script>
- class Spark { // 爆炸火花
- constructor({
- x,
- y,
- color,
- ctx,
- sparks,
- die
- },
- angle) {
- this.px = x;
- this.py = y;
- this.x = 0;
- this.y = 0;
- this.color = color;
- this.angle = angle;
- this.ctx = ctx;
- this.target = 50 + 80 * Math.random();
- this.speed = 2 + 2 * Math.random();
- this.size = 4 + 2 * Math.random();
- this.sparks = sparks;
- this.die = die;
- }
- move() {
- if (this.x < this.target) {
- this.x += this.speed;
- } else {
- this.sparks.delete(this); ! this.sparks.size && this.die();
- }
- }
- draw() {
- this.ctx.save();
- this.ctx.translate(this.px, this.py);
- this.ctx.rotate(this.angle);
- this.ctx.fillStyle = this.color;
- this.ctx.fillRect(this.x, this.y, this.size, this.size);
- this.ctx.restore();
- }
- }
- class Fireworks { // 烟花
- constructor({
- canvas,
- ctx
- }) {
- this.ctx = ctx;
- this.x = Math.random() * canvas.width;
- this.y = 0;
- this.speed = 4 + 2 * Math.random();
- this.targetY = (1 + Math.random()) / 2 * canvas.height; // 爆炸高度
- this.size = 3 + 2 * Math.random();
- this.color = '#' + (0xffffff * Math.random() | 0).toString(16).padStart(6, '0');
- this.sparks = new Set(); // 爆炸火花
- this.die = () = >{
- this.dead = true;
- };
- }
- rise() { // 烟花上升
- this.y += this.speed;
- if (this.y >= this.targetY) {
- if (!this.sparks.size) { // 爆炸, 添加火花
- let num = 30 + parseInt(40 * Math.random()),
- // 火花数
- i = num;
- while (i--) {
- this.sparks.add(new Spark(this, 2 * Math.PI * i / num));
- }
- } else { // 已经爆炸了
- this.sparks.forEach(spark = >spark.move());
- }
- }
- }
- draw() {
- if (this.y > this.targetY) {
- // 绘制爆炸火花
- this.sparks.forEach(spark = >spark.draw());
- } else {
- // 绘制上升的烟花
- this.ctx.fillStyle = this.color;
- this.ctx.fillRect(this.x, this.y, this.size, this.size);
- }
- }
- }
- let page = {
- init() {
- this.canvas = document.querySelector('canvas');
- this.ctx = this.canvas.getContext('2d');
- this.fireworks = new Set();
- this.addEventListener();
- this.onResize();
- this.draw();
- },
- onResize() {
- let style = getComputedStyle(this.canvas);
- // 设置 canvas 绘图尺寸, 会重置 canvas
- this.canvas.width = parseFloat(style.width);
- this.canvas.height = parseFloat(style.height);
- // 调整 canvas 坐标系, 以左下角为坐标原点, y 轴向上
- this.ctx.scale(1, -1);
- this.ctx.translate(0, -this.canvas.clientHeight);
- // 重设烟花
- this.fireworks.clear();
- for (let i = 0; i < 10; i++) {
- this.fireworks.add(new Fireworks(this));
- }
- },
- addEventListener() {
- window.addEventListener('resize', () = >this.onResize());
- },
- draw() {
- this.ctx.fillStyle = 'rgba(0,0,0,.25)';
- this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
- // 绘制烟花
- this.fireworks.forEach(firework = >{
- if (firework.dead) {
- this.fireworks.delete(firework);
- } else {
- firework.draw();
- firework.rise();
- }
- });
- // 新增烟花
- Math.random() < 0.04 && this.fireworks.add(new Fireworks(this));
- requestAnimationFrame(() = >this.draw());
- }
- };
- page.init();
- </script>
- </body>
- </html>
来源: http://www.qdfuns.com/article/17631/7b93fa05b999eb399d91069824b52d26.html