1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| <!DOCTYPE html> <html>
<head> <title>动画(烟花+完整版)</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="图形系统开发实战:基础篇 示例"> <meta name="author" content="hjq"> <meta name="keywords" content="canvas,ladder,javascript"> <script src="/examples/canvas-qa/canvas_1b/js/helper.js"></script> </head>
<body style="overflow: hidden; margin:10px;"> <canvas id="canvas" width="800" height="400" style="border:solid 1px #CCCCCC;"></canvas><br> <div class="checkbox" style="margin-top:10px;"> <span style="font-size:20px;">点击画布可产生烟花</span> <label style="margin-left:500px;"><input id="chkAuto" type="checkbox" checked>自动产生烟花</label> </div> </body> <script> let canvas = document.getElementById('canvas'); let ctx = canvas.getContext('2d'); let fireworks = []; let debug = false, times = 0, lastTime, fps = 0, timeRatio = 1;
ctx.fillStyle = "rgb(0,0,0)"; ctx.fillRect(0, 0, canvas.width, canvas.height); drawGrid('lightgray', 0, 0, ctx);
class Firework { constructor(x, y) { this.x = x; this.y = y;
this.sparkCount = getRandomNum(5, 14); this.sparkSize = 2; this.sparkRadius = 10;
this.gravity = 1; this.speed = 2; this.decay = 0.98;
this.alpha = 1; this.color = 15 * getRandomNum(0, 24); }
draw() { for (let i = 0; i < this.sparkCount; i++) { let angle = i * 360 / this.sparkCount; let cx = this.x + Math.cos(toRadians(angle)) * this.sparkRadius let cy = this.y + Math.sin(toRadians(angle)) * this.sparkRadius ctx.beginPath(); ctx.arc(cx, cy, this.sparkSize, Math.PI * 2, false); ctx.closePath(); ctx.fillStyle = "hsl(" + this.color + ",100%, 50%," + this.alpha + ")"; ctx.fill(); } }
update() { this.y += this.gravity * timeRatio; this.sparkRadius = this.sparkRadius + this.speed * timeRatio; this.speed = this.speed * this.decay; this.sparkSize = this.sparkSize < 7 ? this.sparkSize + 0.02 : this.sparkSize; this.alpha -= 0.01 * timeRatio; return this.alpha > 0.1; } }
function randomFireworks(x, y) { let num = getRandomNum(5, 10); for (let i = 0; i < num; i++) { fireworks.push(new Firework(x + getRandomNum(-50, 50), y + getRandomNum(-50, 50))); } }
function calculateFps() { times++; if (Date.now() >= lastTime + 1000) { fps = times; timeRatio = 60 / fps; times = 0; lastTime = Date.now(); } }
function frame() { calculateFps();
if (times % 60 === 0 || debug === false) { ctx.fillStyle = "rgba(0, 0, 0, 0.05)"; ctx.fillRect(0, 0, canvas.width, canvas.height); drawGrid('lightgray', 0, 0, ctx);
for (let i = fireworks.length - 1; i >= 0; i--) { fireworks[i].draw(); if (!fireworks[i].update()) { fireworks.splice(i, 1); } }
if (!debug && fireworks.length < 10 && document.getElementById("chkAuto").checked === true) { randomFireworks(getRandomNum(50, canvas.width - 50), getRandomNum(50, canvas.height - 100)); } } window.requestAnimationFrame(frame); } window.requestAnimationFrame(frame);
canvas.addEventListener('click', function (e) { randomFireworks(e.offsetX, e.offsetY); });
</script>
</html>
|