Advertisement

PixiJS Displacement Ripple Zoom

| by Vladimir | 3 min read | code by Joost Kiens
Advanced

Tech & Dependencies

HTML PostCSS Babel
pixi-js gsap-js SplitText.js

Features

  • Displacement Filter
  • Ripple Effect
  • Image Zoom
  • Text Reveal

Browser Support

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

Core

This is a PixiJS Displacement Ripple Zoom. It transforms a static background image into an interactive, liquid-like surface that expands outward from the user’s cursor upon clicking. Its function is to serve as a dramatic, cinematic entrance animation for hero sections or landing pages, shifting visual focus while seamlessly introducing secondary UI elements.

Specs

  • Weight: ~1.5 MB (Dependencies: PixiJS, TweenMax, SplitText).
  • Performance: GPU-intensive. The continuous requestAnimationFrame loop combined with WebGL DisplacementFilter requires a capable graphics processor to maintain 60fps.
  • Theming / Customization: The background image and displacement map are easily swappable via the mainImgSrc and displacementImgSrc constants.
  • Responsiveness: Fluid. A custom resize method updates the PIXI application bounds and recalculates the mask dimensions natively when the viewport shifts.
  • Web APIs: WebGL API, requestAnimationFrame.
  • Graceful Degradation: [!] Complete failure without JavaScript or WebGL support. The user will stare at a blank, dark screen. The UI elements (.Menu, .Logo) start with opacity: 0 in CSS, meaning they will remain permanently invisible if the JS timeline doesn’t execute.

Anatomy

  • HTML: A minimal .App wrapper containing hidden text nodes (.Logo, .Menu, .Payoff). The entire visual experience is injected as a <canvas> element by PixiJS.
  • CSS: Stripped down. It manages absolute positioning for the text nodes and handles basic media queries for typography scaling. It intentionally hides elements initially (opacity: 0).
  • JS: The powerhouse. It leverages PixiJS for WebGL rendering, defining classes for the background, main image, and displacement sprites. GSAP (TweenMax) orchestrates the complex timeline, linking the WebGL distortion scale to the CSS text reveal.

Logic

The standout logic is the mathematical calculation required to guarantee the ripple displacement perfectly covers the entire screen, regardless of where the user clicks.

const maxX = evt.data.global.x - width / 2 > 0 ? evt.data.global.x : width - evt.data.global.x;
const maxY = evt.data.global.y - height / 2 > 0 ? evt.data.global.y : height - evt.data.global.y;

const rippleDiameter = Math.sqrt(maxX * maxX + maxY * maxY) * 2;
const maxScale = (rippleDiameter / 100);

tl.to(displacementSprite, 2.4, {
  pixi: { scaleX: maxScale, scaleY: maxScale * screenRatio }
});

Instead of hardcoding a massive scale value, the script calculates the exact geometric distance from the click coordinates to the furthest corner of the screen using the Pythagorean theorem (Math.sqrt(a^2 + b^2)). It then scales the displacement sprite specifically to that diameter. This ensures the visual distortion exactly clears the viewport bounds before fading out, optimizing rendering without premature visual clipping.

Feel

Cinematic and disruptive. The initial hover state provides a subtle, heavy zoom. The click triggers an explosive, viscous ripple that warps the image like physical glass before snapping into sharp, full-screen focus. The Bounce.easeOut applied to the displacement sprite gives the shockwave a tactile, vibrating decay, while the staggered text reveal grounds the interaction back into a readable digital interface.

Advertisement