↑ Move your cursor left and right
Move your cursor to the left edge of the Ampeur hero and the photograph starts to dissolve. Pixels migrate toward their neighbors. Colors streak along columns. At the far left, the image has sorted itself into pure abstraction bands of color that used to be fabric, skin, light. Move right and it resolves back into a photograph.
That interaction isn't decorative. Ampeur is a fashion label where the photograph is the product not the garment in the photograph, the photograph itself. The hero makes that positioning interactive before a word is read. The image is present but not static, familiar but not comfortable. That's the brand.
Pixel sorting is a glitch art technique. For each column of an image, you identify spans of pixels that meet some threshold condition brightness, saturation, hue and sort those spans by luminance. The sorted columns produce the characteristic streaking effect: colors bleed toward their neighbors, gradients form where hard edges used to be.
The threshold is the critical variable. A low threshold affects almost no pixels the image stays intact. A high threshold pulls in the entire column the image sorts completely. Mapping cursor x-position to this threshold gives you the drag interaction: every position in the range produces a distinct, deterministic image state.
IMPLEMENTATION DETAIL
The key constraint
The sorted output is computed against the original pixel data, not the previous frame so every cursor position is idempotent. Dragging back to 0.5 always produces the same image.
Source pixels held in an immutable Int32Array
The canvas is sized to the container. On mouse move, the normalized x-position drives the sort threshold directly no easing, no spring. The frame only redraws when the cursor has actually moved (last position is stored and compared), so the animation loop runs at zero cost when the user is still.
The component is dynamically imported with ssr: false so the canvas and image loading stay entirely client-side. The server bundle stays clean. On mobile, a default threshold of 0.5 renders the mid-sort state the effect communicates even without the interaction.
The sort runs on the CPU in a requestAnimationFrame loop. For a 1200×800 image, each frame sorts approximately 800 columns each column scan is O(n) in column height. The total per-frame budget is around 2–4ms on mid-range hardware, well within the 16ms frame budget at 60fps.
The working buffer is a typed Int32Array allocated once at image load. No garbage collection pressure during animation. Pixel data is written directly to the canvas via putImageData no intermediate DOM objects in the hot path.