HTML5 Canvas super realistic fireworks bloom animation

Hello front-end friends! The May Day holiday is coming to an end. Before starting the overtime mode, I want to share with you a super cool and super realistic HTML5 Canvas fireworks simulation animation. This upgraded version of fireworks animation has the following features:

  • When the fireworks bloom, they will show different colors, unlike previous versions of a firework that only had one color.
  • The color of the night sky will automatically adapt to the color of the fireworks currently blooming, and the effect will be more realistic.
  • The shape of each firework when it blooms is no longer the same as before, but randomly changes to different patterns, which is more in line with the actual fireworks scene.
  • Users can set some parameters, such as enabling sound effects, pattern selection, image quality selection and full screen settings, etc.

Let's take a look at the renderings first, it's very spectacular!

Effect preview

Code

HTML code

The HTML code is mainly composed of two parts, one is the setting panel form, and the other is the animation carrier canvas element.

The setting panel button is implemented through SVG:

<div style="height: 0; width: 0; position: absolute; visibility: hidden;">
	<svg xmlns="http://www.w3.org/2000/svg">
		<symbol id="icon-play" viewBox="0 0 24 24">
			<path d="M8 5v14l11-7z"/>
		</symbol>
		<symbol id="icon-pause" viewBox="0 0 24 24">
			<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
		</symbol>
		<symbol id="icon-close" viewBox="0 0 24 24">
			<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
		</symbol>
		<symbol id="icon-settings" viewBox="0 0 24 24">
			<path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/>
		</symbol>
		<symbol id="icon-sound-on" viewBox="0 0 24 24">
			<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>
		</symbol>
		<symbol id="icon-sound-off" viewBox="0 0 24 24">
			<path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/>
		</symbol>
	</svg>
</div>

Corresponds to the 3 control buttons on the interface:

<div class="controls">
			<div class="btn pause-btn">
				<svg fill="white" width="24" height="24"><use href="#icon-pause" xlink:href="#icon-pause"></use></svg>
			</div>
			<div class="btn sound-btn">
				<svg fill="white" width="24" height="24"><use href="#icon-sound-off" xlink:href="#icon-sound-off"></use></svg>
			</div>
			<div class="btn settings-btn">
				<svg fill="white" width="24" height="24"><use href="#icon-settings" xlink:href="#icon-settings"></use></svg>
			</div>
</div>

There is nothing special about the HTML code of the settings menu, it is just composed of some checkbox es and select drop-down box controls, which will not be expanded here.

As for the animation carrier canvas, we can directly place the canvas element on the page:

<div class="canvas-container">
			<canvas id="trails-canvas"></canvas>
			<canvas id="main-canvas"></canvas>
</div>

CSS code is mainly used to control the style of the settings panel, and we will not expand it here.

JavaScript code

After the page is loaded, the fireworks animation application begins to initialize, mainly applying the current settings, and starting the fireworks animation according to the settings:

function init() {
	// Remove the loading animation when the page is initialized
	document.querySelector('.loading-init').remove();
	appNodes.stageContainer.classList.remove('remove');
	
	// populate dropdown
	function setOptionsForSelect(node, options) {
		node.innerHTML = options.reduce((acc, opt) => acc += `<option value="${opt.value}">${opt.label}</option>`, '');
	}

	// Type of fireworks
	let options = '';
	shellNames.forEach(opt => options += `<option value="${opt}">${opt}</option>`);
	appNodes.shellType.innerHTML = options;
	// firework size
	options = '';
	['3"', '4"', '6"', '8"', '12"', '16"'].forEach((opt, i) => options += `<option value="${i}">${opt}</option>`);
	appNodes.shellSize.innerHTML = options;
	
	setOptionsForSelect(appNodes.quality, [
		{ label: 'Low', value: QUALITY_LOW },
		{ label: 'Normal', value: QUALITY_NORMAL },
		{ label: 'High', value: QUALITY_HIGH }
	]);
	
	setOptionsForSelect(appNodes.skyLighting, [
		{ label: 'None', value: SKY_LIGHT_NONE },
		{ label: 'Dim', value: SKY_LIGHT_DIM },
		{ label: 'Normal', value: SKY_LIGHT_NORMAL }
	]);
	
	// Mobile app 0.9
	setOptionsForSelect(
		appNodes.scaleFactor,
		[0.5, 0.62, 0.75, 0.9, 1.0, 1.5, 2.0]
		.map(value => ({ value: value.toFixed(2), label: `${value*100}%` }))
	);
	
	// Start playing
	togglePause(false);
	
	// Initialize the animation canvas
	renderApp(store.state);
	
	// Apply and update the configuration
	configDidUpdate();
}

Next are the core methods update(frameTime, lag) and render(speed) implemented by fireworks animation. Mainly using mathematical methods to calculate the trajectory of the particles when the fireworks bloom:

const burnRate = Math.pow(star.life / star.fullLife, 0.5);
const burnRateInverse = 1 - burnRate;

star.prevX = star.x;
star.prevY = star.y;
star.x += star.speedX * speed;
star.y += star.speedY * speed;
// Apply air drag if star isn't "heavy". The heavy property is used for the shell comets.
if (!star.heavy) {
	star.speedX *= starDrag;
	star.speedY *= starDrag;
}
else {
	star.speedX *= starDragHeavy;
	star.speedY *= starDragHeavy;
}
star.speedY += gAcc;

if (star.spinRadius) {
	star.spinAngle += star.spinSpeed * speed;
	star.x += Math.sin(star.spinAngle) * star.spinRadius * speed;
	star.y += Math.cos(star.spinAngle) * star.spinRadius * speed;
}

if (star.sparkFreq) {
	star.sparkTimer -= timeStep;
	while (star.sparkTimer < 0) {
		star.sparkTimer += star.sparkFreq * 0.75 + star.sparkFreq * burnRateInverse * 4;
		Spark.add(
			star.x,
			star.y,
			star.sparkColor,
			Math.random() * PI_2,
			Math.random() * star.sparkSpeed * burnRate,
			star.sparkLife * 0.8 + Math.random() * star.sparkLifeVariation * star.sparkLife
		);
	}
}

The code for animation rendering is as follows:

while (BurstFlash.active.length) {
	const bf = BurstFlash.active.pop();
	
	const burstGradient = trailsCtx.createRadialGradient(bf.x, bf.y, 0, bf.x, bf.y, bf.radius);
	burstGradient.addColorStop(0.024, 'rgba(255, 255, 255, 1)');
	burstGradient.addColorStop(0.125, 'rgba(255, 160, 20, 0.2)');
	burstGradient.addColorStop(0.32, 'rgba(255, 140, 20, 0.11)');
	burstGradient.addColorStop(1, 'rgba(255, 120, 20, 0)');
	trailsCtx.fillStyle = burstGradient;
	trailsCtx.fillRect(bf.x - bf.radius, bf.y - bf.radius, bf.radius * 2, bf.radius * 2);
	
	BurstFlash.returnInstance(bf);
}

The above is the implementation process of this HTML5 fireworks animation. At the end of the article, all the source code will be shared with you.

Source code download

I have compiled a source code package for the complete code for everyone to download and study.

Source code download address: https://mp.weixin.qq.com/s/hfghyk1d-FjTPU5hj_ekZA

The code is for reference and learning only, please do not use it for commercial purposes.

final summary

This HTML5 Canvas firework animation should be regarded as the pinnacle of web page firework simulation animation. If you have better ideas and creativity, please leave a message and let us know.

Tags: html5 canvas

Posted by forzatio on Wed, 04 May 2022 16:21:39 +0300