Advertisement

Shattering Image Gallery Transition

| by Vladimir | 3 min read | code by Kevin Levron
Advanced

Tech & Dependencies

HTML CSS JavaScript
ThreeJS GSAP

Features

  • WebGL Shaders
  • Instanced Rendering
  • Scroll Navigation
  • Mouse Parallax

Browser Support

Chrome 60+ Edge 79+ Firefox 55+ Safari 11+

Core

This is a Shattering Image Gallery Transition. It utilizes the WebGL API via Three.js to deconstruct 2D images into a matrix of 3D particles. Its function is to replace standard fade or slide slideshows with a highly cinematic, physics-based explosion effect, transitioning between photographs by blowing the current image apart to reveal the next one underneath.

Specs

  • Weight: Heavy. Requires Three.js and GSAP libraries, plus high-resolution image textures.
  • Performance: Highly optimized. It uses InstancedMesh and custom GLSL vertex shaders, allowing the browser to render and animate thousands of individual square fragments in a single draw call, maintaining 60 FPS.
  • Theming / Customization: Controlled via the conf object in JavaScript, where you define the size of the shatter fragments and an array of image URLs.
  • Responsiveness: Re-evaluates camera aspect ratio, plane geometry, and UV mapping on window resize to ensure the image covers the viewport without stretching.
  • Web APIs: WebGL API, HTML Canvas API.
  • Graceful Degradation: [!] Fails completely to a blank screen if WebGL is unsupported or JavaScript is disabled. There is no fallback HTML structure.

Anatomy

The architecture bypasses the DOM entirely, rendering directly to a <canvas> element.

  • HTML/CSS (The Skeleton & Skin): A barebones, full-screen <canvas id="canvas">. CSS removes margins and sets the cursor to a pointer.
  • JS (The Nervous System):
    1. State Management: Tracks scroll/click inputs to update the targetProgress variable.
    2. Texture Loading: Preloads all images using THREE.TextureLoader to prevent mid-animation stuttering.
    3. Plane Construction: Generates an InstancedMesh grid (plane1, plane2), mathematically calculating the required rows (ny) and columns (nx) based on viewport size.
    4. Custom Shaders: Overrides the standard MeshBasicMaterial vertex shader to inject custom translation (offset) and rotation matrices for the explosion physics.

Logic

The core optimization is “Instanced UV Mapping and Custom Vertex Shaders”:

shader.vertexShader = shader.vertexShader.replace('#include <project_vertex>', `
  mat3 rotMat = rotationMatrixXYZ(progress * rotation);
  transformed = rotMat * transformed;

  vec4 mvPosition = vec4(transformed, 1.0);
  #ifdef USE_INSTANCING
    mvPosition = instanceMatrix * mvPosition;
  #endif

  mvPosition.xyz += progress * offset;
  mvPosition = modelViewMatrix * mvPosition;
  gl_Position = projectionMatrix * mvPosition;
`);

Instead of updating the x, y, z coordinates of 5,000 individual meshes in a JavaScript loop every frame (which would crash the CPU), the code passes a single progress uniform (from 0 to 1) to the GPU. The GPU shader then multiplies this uniform by a pre-calculated random offset and rotation attribute unique to each instance. The GPU executes this math in parallel for every single fragment simultaneously, resulting in a buttery-smooth explosion.

Feel

Violent, kinetic, and deeply satisfying. Scrolling the mouse wheel feels like scrubbing through a video timeline of an explosion; you can pause mid-shatter, reverse the explosion to piece the image back together, or click to blast the image toward the camera. The subtle mouse parallax (tiltX, tiltY) adds a continuous layer of depth, making the flat photographs feel like physical glass panels waiting to be broken.

Advertisement