jnordberg / gif.js

JavaScript GIF encoding library
http://jnordberg.github.io/gif.js/
MIT License
4.74k stars 668 forks source link

Delay in rendered GIF #116

Open iamnottheway opened 4 years ago

iamnottheway commented 4 years ago

I'm using gifjs to convert a canvas animation into a GIF and so far it has worked alright. But the problem I'm facing is that the resulting output has some sort of delay in between each frame, so the animation is pretty slow. I've tried setting the delay value in addFrame to the lowest value possible but for some reason, it just doesn't seem to work.

Here's the example, as you can see it's very slow.

animated-asset (7)

Is there a way to remove this delay? Am I doing something wrong? I'd appreciate any help, thanks!

1j01 commented 4 years ago

GIF viewers have a minimum delay below which it will default to a longer delay. Try increasing the delay to 20ms.

iamnottheway commented 4 years ago

@1j01 I tried it, doesn't work. For some reason, it makes it slower. I think it's the library?

1j01 commented 4 years ago

I don't know. If you play around with the delay, can you find a point at which decreasing the delay stops making it faster? Also, if you only need a handful of gifs, https://ezgif.com/speed is good for this.

ahmedmaazin commented 4 years ago

@HarowitzBlack May I ask you what short of canvas animation is it? A Lottie Animation?

I had a similar issue while doing Lottie to GIF. Solved it by calculating the delay ms value based on the animation frame rate. Let me know.

iamnottheway commented 4 years ago

@ahmedmaazin Hi yes, it was a Lottie animation. I was trying to convert Lottie to GIF. Would you be kind enough to tell me how you did it? Thank you!

ahmedmaazin commented 4 years ago

@HarowitzBlack Sure let me try to explain below...:

// Calculate the ms delay by the Lottie instance frame rate. this.delay = (1 / this.lottie.frameRate) * 1000;

// Set the delay here. gif.addFrame(img, {delay: this.delay});

Let me know how it goes. Also do share some sample snippet of your implementation.

iamnottheway commented 4 years ago

Thank you so much, It's working!! I'm using fabricjs to load the little into the fabricjs canvas and passing each frame of it into gif.js to render it. Here's a snippet of it

` const fabricGIFCanvas = gifRender.fabricCanvas; const animItem = gifRender.animatedBodyMovinContent; const delay = (1 / animItem.frameRate) * 1000;

    fabricGIFCanvas.clear();
    fabricGIFCanvas.setHeight(450);
    fabricGIFCanvas.setWidth(600);

    animItem.addEventListener('enterFrame', e => {
      fabricGIFCanvas.requestRenderAll();
      this.state.gifObject.addFrame(fabricGIFCanvas.lowerCanvasEl, {
        delay: delay,
        copy: true,
      });
    });

    animItem.addEventListener('complete', e => {
      this.state.gifObject.render();
    });

    animItem.addEventListener('DOMLoaded', () => {
      window.tempEl = animItem;
      animItem.goToAndStop(1, true);
      const fabricImage = new fabric.fabric.AEAnimation(gifCanvas, {
        objectCaching: true,
        scaleX: 0.8,
        scaleY: 0.8,
      });
      fabricGIFCanvas.add(fabricImage);
      fabricGIFCanvas.centerObject(fabricImage);

      fabricGIFCanvas.requestRenderAll();
      animItem.play();
      this.setState({
        animItem: animItem,
      });
    });

`

ahmedmaazin commented 4 years ago

Nice. Glad to hear that it works. 👍