Search code examples
jqueryanimationsvggifanimated-gif

Play one part of GIF first, then loop a certain section indefinitely


I have an animated gif with transparency over at my website here.

Ideally I would like this to play the animation once and then repeat a few frames that has the entire logo in it, but it doesn't look like a single gif will be able to accomplish this.

Doing some research it looks like I have a few options, but I'm not sure what's best in a scenario like this.

  1. Use javascript to time the gif and then swap images out when it should be done playing. This seems very unreliable and on slow connections it probably won't function like I want to at all. I don't think there's other ways to detect when a gif animation has finished playing, but I might be wrong on that.

  2. Use a format other than gif that might be able to accomplish this for me.

  3. Edit the gif so that it only plays through once, and make the last frame a still of what I'd like. This would remove any animation and I'd rather go for that hand drawn, animated feel but I have a feeling I might end up doing this.

  4. Somehow find a pure javascript/svg + path solution which seems incredibly difficult & not something that I can do relatively quickly at all.

Has anyone faced a problem similar to this that has any suggestions?


Solution

  • Combine all the frames into a single filmstrip image (transparent PNG would be best, with antialiasing if possible). Set this as the background of a div element with the height of a single frame, and then animate over the required frames by setting the background-position CSS property to suitable values.

    Here's a simple example made with a filmstrip image containing 14 frames, where the last 3 frames are played in a loop:

    $(function() {
      var ani = {
        frame_height: 200,
        num_frames: 14,
        loop_frame: 11,
        frame_duration: 125,
        cur_frame: 0
      };
      window.setInterval(
        function() {
          $('#draw').css( 'background-position-y',
                          (-ani.frame_height * ani.cur_frame ) + 'px'
                        );
          ani.cur_frame = (ani.cur_frame + 1) % ani.num_frames;
          if (ani.cur_frame == 0) ani.cur_frame = ani.loop_frame;
        },
        ani.frame_duration
      );
    });
    #draw {
      width: 200px;
      height: 200px;
      margin: 0 auto;
      background: url(https://i.sstatic.net/ppyyt.png) top center;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="draw"></div>

    Note: If you set the default background of the animated div to the first frame of the animation, you don't need to set an onload event handler because JQuery will only run your code once it has loaded.

    To convert your animated GIF into a filmstrip, I recommend using ImageMagick. There are just two simple steps:

    1. Unpack the animated GIF into a numbered series of individual frames:

      convert -coalesce Logo-norepeat-transparent-white-big.gif f_%05d.png
      
    2. Stitch these frames together, one above the other:

      convert -append f_[0-9]*.png logo_frames.png
      

    If the frames in your GIF animation have different durations, then things will be a little more complicated, but the basic principle is the same.