Create Interactive Pixelated Image Transitions with JavaScript

Category: Animation , Javascript | February 28, 2025
Author:osmosupply
Views Total:0 views
Official Page:Go to website
Last Update:February 28, 2025
License:MIT

Preview:

Create Interactive Pixelated Image Transitions with JavaScript

Description:

This project presents a dynamic way to transition between images. When you hover over an image, it transforms into another through a pixelated effect.

The transition breaks the image into a grid of small squares that randomly appear and disappear. This creates a digital dissolve effect between two images.

See It In Action:

How to use it:

1. Add the following HTML structure for each image card you want to include. The structure contains:

  • A container with data attributes for targeting
  • A default image that appears initially
  • An active image that appears after the transition
  • A grid container that will hold the pixels for the transition effect
<div data-hover="" data-pixelated-image-reveal="" class="pixelated-image-card">
  <div class="before__100"></div>
  <div class="pixelated-image-card__default">
    <img src="1.jpg" width="400" alt="" class="pixelated-image-card__img">
  </div>
  <div data-pixelated-image-reveal-active="" class="pixelated-image-card__active">
    <img src="2.jpg" width="400" alt="" class="pixelated-image-card__img">
  </div>
  <div data-pixelated-image-reveal-grid="" class="pixelated-image-card__pixels">
    <div class="pixelated-image-card__pixel"></div>
  </div>
</div>

2. Add the following CSS snippets to the page. These styles create the container structure and set up the positioning for the transition components.

.pixelated-image-card {
  background-color: #131313;
  color: #ff4c24;
  border-radius: .5em;
  width: 30vw;
  max-width: 100%;
  position: relative;
  overflow: hidden;
}
.before__100 {
  padding-top: 100%;
}
.pixelated-image-card__default,
.pixelated-image-card__img,
.pixelated-image-card__active,
.pixelated-image-card__pixels{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
.pixelated-image-card__active {
  display: none;
}
.pixelated-image-card__pixel {
  background-color: currentColor;
  width: 100%;
  height: 100%;
  display: none;
  position: absolute;
}

3. Add the GSAP animation library to your HTML document:

<script src="/dist/gsap.min.js"></script>

4. Add this JavaScript code to enable the pixelated transition effect:

document.addEventListener('DOMContentLoaded', function () {
  const animationStepDuration = 0.3; // Adjust this value to control the timing
  const gridSize = 7; // Number of pixels per row and column (adjustable)
  // Calculate pixel size dynamically
  const pixelSize = 100 / gridSize; // Calculate the size of each pixel as a percentage
  // Select all cards
  const cards = document.querySelectorAll('[data-pixelated-image-reveal]');
  // Detect if device is touch device
  const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || window.matchMedia("(pointer: coarse)").matches;
  // Loop through each card
  cards.forEach((card) => {
    const pixelGrid = card.querySelector('[data-pixelated-image-reveal-grid]');
    const activeCard = card.querySelector('[data-pixelated-image-reveal-active]');
    // Remove any existing pixels with the class 'pixelated-image-card__pixel'
    const existingPixels = pixelGrid.querySelectorAll('.pixelated-image-card__pixel');
    existingPixels.forEach(pixel => pixel.remove());
    // Create a grid of pixels dynamically based on the gridSize
    for (let row = 0; row < gridSize; row++) {
      for (let col = 0; col < gridSize; col++) {
        const pixel = document.createElement('div');
        pixel.classList.add('pixelated-image-card__pixel');
        pixel.style.width = `${pixelSize}%`; // Set the pixel width dynamically
        pixel.style.height = `${pixelSize}%`; // Set the pixel height dynamically
        pixel.style.left = `${col * pixelSize}%`; // Set the pixel's horizontal position
        pixel.style.top = `${row * pixelSize}%`; // Set the pixel's vertical position
        pixelGrid.appendChild(pixel);
      }
    }
    const pixels = pixelGrid.querySelectorAll('.pixelated-image-card__pixel');
    const totalPixels = pixels.length;
    const staggerDuration = animationStepDuration / totalPixels; // Calculate stagger duration dynamically
    let isActive = false; // Variable to track if the card is active
    let delayedCall;
    const animatePixels = (activate) => {
      isActive = activate;
      gsap.killTweensOf(pixels); // Reset any ongoing animations
      if (delayedCall) {
        delayedCall.kill();
      }
      gsap.set(pixels, { display: 'none' }); // Make all pixels invisible instantly
      // Show pixels randomly
      gsap.to(pixels, {
        display: 'block',
        duration: 0,
        stagger: {
          each: staggerDuration,
          from: 'random'
        }
      });
      // After animationStepDuration, show or hide the activeCard
      delayedCall = gsap.delayedCall(animationStepDuration, () => {
        if (activate) {
          activeCard.style.display = 'block';
          // **Set pointer-events to none so clicks pass through activeCard**
          activeCard.style.pointerEvents = 'none';
        } else {
          activeCard.style.display = 'none';
        }
      });
      // Hide pixels randomly
      gsap.to(pixels, {
        display: 'none',
        duration: 0,
        delay: animationStepDuration,
        stagger: {
          each: staggerDuration,
          from: 'random'
        }
      });
    };
    if (isTouchDevice) {
      // For touch devices, use click event
      card.addEventListener('click', () => {
        animatePixels(!isActive);
      });
    } else {
      // For non-touch devices, use mouseenter and mouseleave
      card.addEventListener('mouseenter', () => {
        if (!isActive) {
          animatePixels(true);
        }
      });
      card.addEventListener('mouseleave', () => {
        if (isActive) {
          animatePixels(false);
        }
      });
    }
  });
});

How It Works:

The JavaScript code first sets up a grid of div elements. These act as the “pixels.” Each pixel is sized and positioned using percentages. This approach makes the grid responsive.

The code then uses GSAP to animate these pixels. When you hover (or tap on touch devices), the pixels are displayed one by one, but with a random start point. It creates the visual transition, and the activeCard is set to visiable. After the animation time which defined in animationStepDuration, these pixels become invisible, also with random start point.

The isTouchDevice check optimizes the interaction. On touch devices, a click triggers the effect. On non-touch devices, the effect is triggered by hovering.

You Might Be Interested In:


Leave a Reply