component 21 / 28WORKING
SC Noise
- type
- Code Component
- platform
- Framer
- license
- SecretoCho Design
demo · runs with JavaScript
Animated canvas grain: a random grey tile re-rolled every N frames and repeated over the layer, with size, scale and alpha controls.
Noise lays an animated film-grain texture over whatever sits behind it. A small tile of random grey pixels is re-rolled every few frames and repeated across a canvas that fills the layer; tile size, horizontal and vertical scale, refresh interval and pixel alpha are the controls.
- Visual
- Effects
- FX
Main
Overview
- Built With
- React (hooks), Canvas 2D, requestAnimationFrame, Framer Code Component API
- Layout Support
- Fixed width and height (intrinsic 400 × 400); the canvas fills the layer
- Orientation
- Full-layer overlay
- Ideal Use Case
- Grain over hero sections, dark backgrounds, photo treatments
Tags
Code comment
Noise.tsx has no doc comment: lines 1–6 hold only Framer’s annotations.
Dependencies
- Technologies
- None (Canvas 2D)
- Notes
- No libraries; one requestAnimationFrame loop while mounted.
Complexity
- Logic Level
- Low (random tile, repeat pattern, frame counter)
- Runtime Cost
- Low–Medium (CPU fills size² pixels per refresh; the rAF loop runs every frame and redraws every Nth)
- Component Size
- ~4 KB TSX (3,978 bytes, 142 lines)
- Notes
- The loop stops through an isMounted flag on unmount; the resize listener is removed.
Guide
Instructions
- Drop Noise over the content it should texture (it is fixed-size: 400 × 400 by default; resize the layer).
- Set Size (the random tile, 100–750 px) and Scale X / Y (0.5–4) for grain coarseness.
- Set Refresh Interval in frames (lower = faster flicker) and Alpha (0–255) for strength.
- Set the layer to ignore pointer events in Framer if content below must stay clickable.
Examples / Presets
Default
The source defaults: a 250 px tile, scale 1, re-rolled every 6 frames at alpha 15.
As on the site
- patternSize
- 200
- patternRefreshInterval
- 50
- patternAlpha
- 20 (the old site’s contact and help pages; their layer’s 0.5 opacity is not a component prop)
Coarse
- patternScaleX
- 3
- patternScaleY
- 3
- patternRefreshInterval
- 4
- patternAlpha
- 40
Film
- patternSize
- 150
- patternRefreshInterval
- 2
- patternAlpha
- 28
Mechanics
How it Works
- Tile: an offscreen canvas of patternSize × patternSize; updatePattern writes a random grey (one value for R, G and B) and patternAlpha into every pixel.
- Draw: drawGrain clears the visible canvas and fills it with createPattern(tile, "repeat").
- Loop: requestAnimationFrame runs every frame; when frame % patternRefreshInterval is 0 the tile is re-rolled and redrawn.
- Resize: the canvas backing store is set to the element size × devicePixelRatio and the context scaled by Scale X / Y; a window resize listener repeats this.
- Cleanup: an isMounted flag ends the loop and the resize listener is removed when the effect re-runs or the component unmounts.
Performance & Tuning
- Cost is patternSize² pixels per refresh on the CPU: 250² = 62,500, 750² = 562,500. Keep the tile small and raise the interval on weak devices.
- The rAF callback runs every frame even between refreshes (it only counts); a long interval still keeps the loop alive.
- Scale X / Y above 1 enlarge the grain without a bigger tile, the cheaper way to coarser noise. Below 1 the grain covers only that fraction of the canvas (0.5 × 0.5: the top-left quarter), because the clear and the fill run under the scale.
Compatibility & Limits
- Evergreen browsers with Canvas 2D.
- Fixed layout size only (@framerSupportedLayoutWidth / Height fixed).
- No prefers-reduced-motion check in the file.
- Refresh Interval counts requestAnimationFrame callbacks, so the grain changes twice as fast on 120 Hz screens.
- Scale X or Y below 1 leaves part of the canvas without grain (above).
Quality
Accessibility
- Purely decorative: give the layer aria-hidden="true".
- Constant flicker can bother motion-sensitive visitors; consider a long interval or pausing under prefers-reduced-motion in a fork.
Security & Privacy
- No network calls, no storage, no permissions, no third-party libraries.
- Math.random only; one window resize listener, removed on cleanup.
Reference
Props
| name | type | default | description |
|---|---|---|---|
patternSize | number | 250 | Size. Size of the noise pattern tile (in pixels), 100–750. |
patternScaleX | number | 1 | Scale X. 0.5–4. Below 1 the grain covers only part of the canvas. |
patternScaleY | number | 1 | Scale Y. 0.5–4. Below 1 the grain covers only part of the canvas. |
patternRefreshInterval | number | 6 | Refresh Interval. Frequency of pattern refresh in frames (lower = faster), 1–100. |
patternAlpha | number | 15 | Alpha. Opacity of the noise pixels (0–255). |
Notes & Tips
- Alpha 10–20 reads as film grain; 60+ as static.
- The greys (0–255 at one alpha) lighten and darken evenly only over a mid-grey fill; over a dark fill they mostly lighten.
Troubleshooting / FAQ
The grain does not cover the layer after a resize
The canvas resizes on the window resize event only; a layer resized without a window resize keeps the old backing size.
High CPU
Lower Size or raise Refresh Interval; the cost is the tile area per refresh.
Source
Key excerpt
Grain is a tile of random grey pixels at one alpha, re-rolled on the CPU and stamped across the canvas as a repeating pattern.
const updatePattern = () => { for (let i = 0; i < patternPixelDataLength; i += 4) { const value = Math.random() * 255 patternData.data[i] = value patternData.data[i + 1] = value patternData.data[i + 2] = value patternData.data[i + 3] = patternAlpha } patternCtx.putImageData(patternData, 0, 0) } const drawGrain = () => { ctx.clearRect(0, 0, canvas.width, canvas.height) const pattern = ctx.createPattern(patternCanvas, "repeat") if (pattern) { ctx.fillStyle = pattern ctx.fillRect(0, 0, canvas.width, canvas.height) } }Credits
Credits
© SecretoCho Design
- license
- SecretoCho Design
SecretoCho Design
Disclaimer
Provided “as is” for visual/UX purposes. Validate performance, accessibility, and licensing within your project.
Proves
Hiring a design engineer?
I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.
sc@secretocho.design