JSFiddle - React, Tailwind, and code Playground
by RAX7
HTML
<canvas id="sequence" width="320" height="240"></canvas>
<canvas id="scroll" width="320" height="240" style="top: 260px"></canvas>
CSS
html {
height: 100%;
}
body {
height: 600%;
}
canvas {
position: fixed;
background-color: #ffffff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cg fill='%23969696' fill-opacity='0.4'%3E%3Cpath fill-rule='evenodd' d='M0 0h4v4H0V0zm4 4h4v4H4V4z'/%3E%3C/g%3E%3C/svg%3E");
}
JavaScript
const framesLink = 'https://i.imgur.com/QvNKsCf.png';
const frameWidth = 320;
const frameHeight = 240;
function loadImg(src) {
return new Promise(resolve => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.crossOrigin = 'Anonymous';
img.src = src;
});
}
loadImg(framesLink).then((image) => {
play(image);
scroll(image);
});
function play(image) {
const fps = 24;
const frames = 30;
const duration = frames / fps * 1000;
const canvas = document.querySelector('#sequence');
const ctx = canvas.getContext('2d');
let begin = 0;
function loop(now) {
begin = begin || now;
const elapsed = now - begin;
const progress = elapsed / duration % 1;
const nf = Math.round(progress * (frames - 1));
const offset = frameWidth * nf;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(image, offset, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
function scroll(image) {
const frames = 30;
const canvas = document.querySelector('#scroll');
const ctx = canvas.getContext('2d');
onScroll();
document.addEventListener('scroll', onScroll);
function onScroll() {
const scrolled = (document.documentElement.scrollTop || document.body.scrollTop) /
((document.documentElement.scrollHeight || document.body.scrollHeight) - document.documentElement.clientHeight);
const nf = Math.round(scrolled * (frames - 1));
const offset = frameWidth * nf;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(image, offset, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
}
}