joyco

Image Sequence

Galleries 69

About

A canvas-based image sequence player that renders frame-by-frame animations with binary progressive loading for smooth playback.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Image Sequence to your project and fits it to your theme.

Code

How Image Sequence is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import { CanvasSequence } from "@/components/ui/image-sequence";
import { useState } from "react";
import { cn } from "@/lib/utils";

const sequences = [
  {
    name: "Grafitty Can",
    frameCount: 71,
    getImagePath: (idx: number) =>
      `https://qfxa88yauvyse9vr.public.blob.vercel-storage.com/sequence-01/Lata${String(idx).padStart(2, "0")}.webp`,
  },
  {
    name: "Sentinel Bot",
    frameCount: 71,
    getImagePath: (idx: number) =>
      `https://qfxa88yauvyse9vr.public.blob.vercel-storage.com/sequence-02/Bot${String(idx).padStart(2, "0")}.webp`,
  },
  {
    name: "Rubber Duck",
    frameCount: 71,
    getImagePath: (idx: number) =>
      `https://qfxa88yauvyse9vr.public.blob.vercel-storage.com/sequence-03/Ducky${String(idx).padStart(2, "0")}.webp`,
  },
];

function ImageSequenceDemo() {
  const [activeIndex, setActiveIndex] = useState(0);

  return (
    <div className="flex min-h-80 w-full items-center justify-center p-8">
      <div className="flex flex-wrap items-center justify-center gap-6">
        {sequences.map((seq, index) => {
          const isActive = index === activeIndex;

          return (
            <div
              key={seq.name}
              className="relative cursor-pointer"
              onMouseEnter={() => setActiveIndex(index)}
            >
              <CanvasSequence
                frameCount={seq.frameCount}
                frameDuration={33}
                getImagePath={seq.getImagePath}
                objectFit="contain"
                isPlaying={isActive}
                resetOnPlay
                width={200}
                height={200}
                className="rounded-lg transition-opacity duration-200"
                style={{ opacity: isActive ? 1 : 0.5 }}
              />

              {/* Active frame indicator */}
              <div
                className={cn(
                  "pointer-events-none absolute inset-0 border-2",
                  isActive
                    ? "border-primary opacity-100"
                    : "border-transparent opacity-0",
                )}
              >
                <span className="bg-primary text-primary-foreground absolute top-0 -left-0.5 -translate-y-full px-1 py-0.5 font-mono text-xs uppercase">
                  {seq.name}
                </span>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

export default ImageSequenceDemo;

More by joyco

View all
  • Infinite List

    Infinite List

    64
  • File Dropzone

    File Dropzone

    19
  • HLS Video Player

    HLS Video Player

    18
  • Action Hint

    Action Hint

    16
  • Chat

    Chat

    15
  • Spritesheet Sequencer

    Spritesheet Sequencer

    11
  • Snake Game

    Snake Game

    2
  • Typewriter

    Typewriter

    2

More in Galleries

View all
  • Thumbnail image viewer

    Thumbnail image viewer

    43
  • Animated Gallery

    Animated Gallery

    1.4K
  • Hero Section 6

    Hero Section 6

    881
  • Editorial Collage Hero

    Editorial Collage Hero

    430
  • Layout Grid

    Layout Grid

    826
  • 3D Parallax Unfurling Gallery

    3D Parallax Unfurling Gallery

    981
  • Image Gallery

    Image Gallery

    90
  • File Upload

    File Upload

    18