JSFiddle - React, Tailwind, and code Playground
by Tintu Raju
HTML
<div class="item disintegration-target">
Welcome
</div>
<div class="item disintegration-target">
Testing
</div>
<div class="item disintegration-target">
Testing another
</div>
<div class="item disintegration-target">
<img...
SCSS
.disintegration-container {
position: absolute;
pointer-events: none;
> canvas {
position: absolute;
left: 0;
top: 0;
transition: transform 1s ease-out, opacity 1s ease-out;
opacity: 1;
transform:
rotate(0deg) translate(0px, 0px) rotate(0deg);
}
}
@keyframes debug-pulse {
0% { filter: none; }
95% { filter: none; }
95% { filter: drop-shadow(0 1px 0 rgba(255,0,0,1)); }
100% { filter: drop-shadow(0 1px 0 rgba(255,0,0,1)); }
}
Babel + JSX
const DEBUG = false;
const REPETITION_COUNT = 2; // number of times each pixel is assigned to a canvas
const NUM_FRAMES = 128;
/**
* Generates the individual subsets of pixels that are animated to create the effect
* @param {HTMLCanvasElement} ctx
* @param {number} count The higher the frame count, the less grouped the pixels will look - Google use 32, but for our elms we use 128 since we have images near the edges
* @return {HTMLCanvasElement[]} Each canvas contains a subset of the original pixels
*/
function generateFrames($canvas, count = 32) {
const { width, height } = $canvas;
const ctx = $canvas.getContext("2d");
const originalData = ctx.getImageData(0, 0, width, height);
const imageDatas = [...Array(count)].map(
(_,i) => ctx.createImageData(width, height)
);
// assign the pixels to a canvas
// each pixel is assigned to 2 canvas', based on its x-position
for (let x = 0; x < width; ++x) {
for (let y = 0; y < height; ++y) {
for (let i = 0; i < REPETITION_COUNT; ++i) {
const dataIndex = Math.floor(
count * (Math.random() + 2 * x / width) / 3
);
const pixelIndex = (y * width + x) * 4;
// copy the pixel over from the original image
for (let offset = 0; offset < 4; ++offset) {
imageDatas[dataIndex].data[pixelIndex + offset]
= originalData.data[pixelIndex + offset];
}
}
}
}
// turn image datas into canvas'
return imageDatas.map(data => {
const $c = $canvas.cloneNode(true);
$c.getContext("2d").putImageData(data, 0, 0);
return $c;
});
}
/**
* Inserts a new element over an old one, hiding the old one
*/
function replaceElementVisually($old, $new) {
const $parent = $old.offsetParent;
$new.style.top = `${$old.offsetTop}px`;
$new.style.left = `${$old.offsetLeft}px`;
$new.style.width = `${$old.offsetWidth}px`;
$new.style.height = `${$old.offsetHeight}px`;
$parent.appendChild($new);
$old.style.visibility =...