Search code examples
javascriptcanvasspritefabricjssprite-sheet

Fabricjs: Sprite sheet to horizontal continuous video thumbnail on canvas


I have multiple sprite sheets, one for each minute of the video. For example if video is 3 min long I have sprite.0.jpg, sprite.1.jpg, sprite.2.jpg which mean 3 sprite sheets each having 60 images for every 1 sec.

That means sprite sheet with 10 columns and 6 rows having single image size as 142x80 whereas total sprite sheet as 1420x 480 (see below)

enter image description here

I want to design component to show preview of continous video thumbnail on canvas. (see below)

enter image description here

How to convert Sprite sheets to horizontal continuous video thumbnail on fabricjs canvas?

I tried drawing the first frame of the sprite sheet on canvas but not sure how to put every sprite sheets in continous manner so that canvas is horizontally scrollable.

// Get the canvas and canvas context
var canvas = document.getElementById("timeline");
var ctx = canvas.getContext("2d");

// Create an image object
var image = new Image();
image.src = "path/to/spritesheet.jpg";

// Wait for the image to load
image.onload = function() {
    // Set the canvas size
    canvas.width = 1420;
    canvas.height = 480;

    // Draw the first frame of the sprite sheet
    ctx.drawImage(image, 0, 0, 1420, 480, 0, 0, canvas.width, canvas.height);
};

Solution

  • I'm just going to focus on the part of your question where you split the sprite sheet into a horizontal continuous thumbnail, there are other concerns that I address after the code sample.

    To do what you ask we need a loop on the sample sprite sheet you provide there are 6 rows so we loop on that and draw the rows into one.

    You are using drawImage with all the parameters, I'm assuming you have the basics clear, if not see more about that in the documentation:
    https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#parameters

    Here is a working sample:

    var canvas = document.getElementById("timeline");
    var ctx = canvas.getContext("2d");
    
    var image = new Image();
    image.src = "https://i.sstatic.net/gOk5s.jpg";
    image.onload = function() {
      for (let i = 0; i < 6; i++)
        ctx.drawImage(
          image,
          0, 80 * i, 1420, 80,
          710 * i, 0, 710, 40
        );
    };
    canvas {
      border: dashed 5px red
    }
    <canvas id="timeline" width=4260 height=40></canvas>


    I do see in your comments you added:

    ... what about when I want see preview of 1 hour long video? This doesn't seems right as there is limit on canvas width I guess.

    Yes there is a limit and is per browser:
    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size

    But That is a much more complex issue that deserves a separate question...

    • one of the options could be combining the sprite tiles, instead of showing thumbnails every 1 second show every 5 or 10 to better accommodate for the large videos
    • another option could be to use multiple canvases