2024-09-30 Design
Create a Dynamic Noisy Logo Using Canvas and SVG in React
By O. Wolfson
In this article, we’ll explore how to create an animated noisy logo effect using HTML canvas and SVG in React. This effect generates random noise on a canvas and reveals the noise through an SVG logo using a mask. This technique can be used for branding, digital art, or creative web animations.
Key Concepts
- HTML Canvas: Used to generate dynamic noise with JavaScript.
- SVG: A scalable vector graphic used to define the logo and apply the mask.
- React: A JavaScript library for building UI components.
Step-by-Step Breakdown
Let’s walk through the code and explain how each part works.
1. Initial Setup
First, we import the necessary React hooks useEffect
and useRef
. We use useEffect
to run the canvas drawing code after the component is rendered and useRef
to access the canvas DOM element.
javascript"use client"; // Ensures the component is client-side
import { useEffect, useRef } from "react";
2. Canvas Noise Generation
Next, we create the NoisyLogo
component. Inside this component, we define a canvasRef
using useRef
to target the <canvas>
element within the component.
javascriptexport default function NoisyLogo() {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas?.getContext("2d");
if (!ctx) return;
const width = 1378;
const height = 562;
canvas.width = width;
canvas.height = height;
2.1. Generate Noise Function
We define a function generateNoise()
that generates random noise on the canvas. It creates an ImageData
object that holds pixel data for the canvas. By looping over each pixel and assigning a random value to the red, green, and blue channels, we create a noise effect.
javascriptfunction generateNoise() {
const imageData = ctx?.createImageData(width, height);
if (!imageData) return;
for (let i = 0; i < imageData.data.length; i += 4) {
const value = Math.random() * 255;
imageData.data[i] = value; // Red
imageData.data[i + 1] = value; // Green
imageData.data[i + 2] = value; // Blue
imageData.data[i + 3] = 255; // Alpha (opacity)
}
ctx?.putImageData(imageData, 0, 0);
}
2.2. Animation with requestAnimationFrame
To continuously update the noise, we use requestAnimationFrame
within the render
function. This ensures that the noise is constantly redrawn, giving it a dynamic "fuzzy TV screen" effect.
javascript const render = () => {
generateNoise();
requestAnimationFrame(render);
};
render();
}, []);
3. SVG Mask and Logo
Now, let's move to the SVG part. The <svg>
element contains the mask and logo that will reveal the noise generated by the canvas. We define a mask using the id="noise-mask"
attribute. Inside the mask, we use two <rect>
elements: one for the black border and one for the white-filled area that defines the mask's shape.
3.1. SVG Mask Definition
The black area hides the noise, and the white area reveals it. The logo path is placed inside the mask and is defined by a complex <path>
element that describes the SVG shape of the logo.
javascript return (
<svg
width="600"
height="245"
viewBox="0 0 1378 562"
xmlns="http://www.w3.org/2000/svg"
style={{ display: "block" }}
>
{/* Define the mask using the SVG logo */}
<mask id="noise-mask">
{/* Add a black border */}
<rect width="100%" height="100%" fill="black" />
{/* The white part for the mask content */}
<rect width="98%" height="98%" fill="white" x="1%" y="1%" />
<g
transform="translate(0.000000,562.000000) scale(0.100000,-0.100000)"
fill="black"
>
<path d="M0 2810 l0 -2810 6890 0 6890 0 0 2810 0 2810 -6890 0 -6890 0 0 -2810z m11960 1630 c102 -9 340 -46 348 -55 4 -3 -106 -556 -110 -560 -2 -2 -37 3 -78 11 -133 23 -204 15 -259 -32 -34 -28 -54 -103 -49 -176 l3 -43 208 -3 207 -2 0 -285 0 -285 -210 0 -210 0 0 -805 0 -805 -390 0 -390 0 0 805 0 805 -175 0 -175 0 0 285 0 285 175 0 175 0 0 78 c0 99 23 239 54 331 98 289 348 451 711 460 28 0 102 -4 165 -9z" />
{/* More path definitions */}
</g>
</mask>
3.2. Embedding the Canvas in the SVG
Finally, we embed the canvas inside the SVG using <foreignObject>
. This element allows us to render regular HTML inside the SVG. The mask="url(#noise-mask)"
attribute is applied to the <foreignObject>
to apply the mask we defined earlier. This causes the canvas noise to be revealed through the SVG logo shape.
javascript {/* Embed the canvas inside the SVG using <foreignObject> */}
<foreignObject width="100%" height="100%" mask="url(#noise-mask)">
<canvas ref={canvasRef} className="w-full h-full" />
</foreignObject>
</svg>
);
}
Key Points to Remember
- Canvas Drawing: The canvas draws random noise using the
generateNoise
function. - Masking in SVG: The SVG mask is defined to reveal certain parts of the canvas noise through the logo.
- React Hooks: We use
useEffect
to generate the noise when the component is mounted, anduseRef
to target the canvas element. - Dynamic Updates: The
requestAnimationFrame
ensures continuous updates to the noise, creating a dynamic effect.
Conclusion
This combination of HTML canvas and SVG in React allows you to create visually striking, animated effects with ease. By leveraging masks in SVG, we can control where the canvas noise is displayed, resulting in a unique logo animation.
This technique can be adapted for various purposes, such as animated backgrounds, interactive elements, or creative web designs.