How to stop an animated gif from looping - javascript

I have an animated gif in an img tag that I start by rewriting the src attribute. The gif was created, though, to loop and I only want it to play once. Is there a way, with Javascript or jQuery, to stop an animated gif from playing more than once?

I was having the same problem with an animated gif. The solution is rather simple.
Open the Animated gif in Photoshop.
Go to the Window tab and select timeline(if the timeline is not already open).
At the bottom of the timeline panel, you will find an option, which says "Forever".
Change that to "Once".
Go to File> Export> Export for Web and save it as a gif.
That should do it.

can you find out how long the gif takes to loop once?
if so then you can stop the image like this:
pseudocode:
wait until the end of the image (when it is about to loop)
create a canvas element that has a static version of the gif as currently displayed drawn on it
hide gif
display canvas element in a way that makes it look like the gif froze
javascript:
var c = $("canvas")[0];
var w = c.width;
var h = c.height;
var img = $("img")[0];
setTimeout(function () {
c.getContext('2d').drawImage(img, 0, 0, w, h);
$(img).hide();
$(c).show();
},10000);
jsfiddle
edit:
I forgot to add reference to the original answer that I took this from, sorry
Stopping GIF Animation Programmatically
that one doesn't address the time factor you need for only one loop
Also, it has been mentioned that this approach is problamatic in certain cases (It actually didn't work when I try it in firefox right now...). so here are a few alternatives:
mentioned by Mark: edit the gif itself to avoid looping. this is the best option if you can.
but I've run into cases where it was not an option (like automated generation of images by a third party)
instead of rendering the static image with canvas, keep a static image version and switch to stop looping . this probablyhas most of the problems as the canvas thing

Based on this answer, it's kinda expensive, but it works. Let's say a single loop takes 2 seconds. At a setTimeout after 2 seconds kick in a setInterval, that would reset image source every millisecond:
setTimeout(function() {
setInterval(function() {
$('#img1').attr('src',$('#img1').attr('src'))
},1)
}, 2000)
again, probably just a proof of concept, but here's demo: http://jsfiddle.net/MEaWP/2/

Actually it is possible to make a gif to stop after just one iteration or any specific number of iterations, see an example below (if it is not already stopped), or in jsfiddle.
To do that the gif must be created with number of iterations specified. This could be done using Screen to Gif, it allows to open a gif or a bunch of images and edit it frame by frame.
This solution also allows you to reset the animation by imgElem.src = imgElem.src; but this does not work in MS IE/Edge.

Jurijs Kovzels's answer works in some condition but not in all.
This is browser-dependent.
It works well with Firefox. But In Google Chrome and Safari, it does not work if the gif is on the same server. The example he provided works because the gif is on the external server.
To restart gifs stored on the internal server, using Google Chrome and Safari, you need extra steps to make it work.
const img = document.getElementById("gif");
img.style = "display: none;";
img.style = "display: block;";
setTimeout(() => {
img.src = img.src;
}, 0);
This is inspired by this answer.

Not sure if this is the best way to respond to everyone and have it appear after all the previous answers and comments, but it seems to work.
I don't have much control over the gif. People post whatever gif they want as the "thankyou.gif in their account directory and then the ThankYou code runs whatever they've put there when a comment is submitted to a form they've posted. So some may loop, some may not, some may be short, some may be long. The solution I've come to is to tell people to make them 5 seconds, because that's when I'm going to fade them out, and I don't care if they loop or not.
Thanks for all the ideas.

I know I am pretty late here but..here it is...
I don't know if you would go to this length but let me share a trick.
Open the GIF in Macromedia Flash 8(it has deprecated since then), Export the GIF as Animated GIF. You will have to choose the file location. After that you would receive a dialog box with settings. In that, add the number of times you want the animation to happen. Click OK. Problem solved.

Related

Automatic Thumbnails/Screenshots for Chapter in HTML Video

I found some examples, where people used a canvas and javascript to take multiple screenshots of a running video.
You can see these examples here or here.
The code sets a time interval, draws the current timeframe to a canvas and uses this to create a screenshot.
I am wondering if it would be possible to use a similar technique, to automatically create a kind of preview for chapters of the video.
But this would require to grab a bunch of screenshots before the video started.
I failed to implement this, so I would like to know, if it is at all possible.
I know that one could use pretaken screenshots for the chapters, but I wanted to automate this process.
Thanks in advance for your answers.
This could be done in theory by jumping to specific times in the video (say every 10 seconds) using video.currentTime, waiting for the frame to be available (using progress events), drawing the frame to a canvas (canvas.drawImage) and storing it in some way (say an array of images having image.src = canvas.toDataURL).
However, this process will take time because at least the relevant parts of the video would need to be loaded in the browser so the frame could be grabbed. The video would not be playable during the process as it is being skipped to different frames.
This behavior is usually not acceptable, but it really depends on your specific use case.

Javascript - preloaded image is rendered late (only for the first time)

I use this code to preload an image:
var image = new Image();
image.addEventListener("load", loadHandler, false);
image.src = "someImage.png";
function loadHandler()
{
// the programme continues
}
Lets say the image refers to a certain button that occurs in the middle of a game.
The problem is that the code waits for a few seconds when the image should be rendered for the first time (using drawImage function). All the other usage (means the image should be shown another time) are instant.
The image is a sprite sheet, size about 3 MB. Everything on a local computer.
If I understand properly your issue, it's not about loading but more about rendering the sprite (which is quite big).
It might help to insert it into the document (wherever you want) and then wait for it to load before doing anything else.
You can hide it with the help of opacity, visibility, etc. properties (any choice should do the trick).
If your target browsers are supporting it, you could also use instead link prefetching.

sync audio to a picture carrousel

Is it possible to sync audio to a picture carrousel without using the canvas? Im currently using setInterval to realize the carrousel. I dont want to use flash and if possible and not too hard to realize, I want to do this without the canvas.
Have you tried a canvas?
Assuming you're using an <audio> element, you can get its currentTime property. This will tell you where the playhead is. You can use this information to change the carousel when the audio passes a certain position, or you can set it to change the audio position when the carousel changes. Whatever works better for what you're doing.
What do you mean by realize the carousel?
I would set a specific timestamp when you want the image to show. So at 12 seconds you want to show image.
You might want to also make sure that the audio is loaded. You can use canPlayThrough to check and see if enough is loaded to play through or you can use audio.buffered.end(0) to check against the length of the audio file and make sure the entire thing has loaded.
Here is a good article for more on this: http://html5doctor.com/html5-audio-the-state-of-play/
When the audio is loaded you call a function and pass in the timestamp and set it as the setInterval time. So at timestamp * 1000 the function will fire and show the image that is passed at that timestamp.
You could also try and use audio.currentTime and fire then, more on that in the article above as well. Let me know if you have a more specific question.

Is there a way to check how much of the picture has been loaded, in pixels, from the top?

The heading sums is all. Though, the case is where I have a long (20x2000px) picture as a sprite for thumbnails. It would be nice if I could start showing the sprite only for the thumbnails that already have required-part of the sprite loaded, and show loader in the meantime.
All I need is to know how much of the picture has been loaded in pixels from the top (supposing that it is not progressive). I thought of using file size to estimate that, though that would be very inaccurate.
The main question everyone is having - why to do this at all?
There is a page that displays somewhat 100 thumbnails. It would be a nice thing if this page had a sprite of those thumbnails generated in the descending thumbnail order.
Such page already exists. The screenshot is attached. User can see a gray placeholder while the sprite is being loaded. I want to display the thumbnail only when the required part of the sprite for that thumbnail is already loaded.
#Guy Sounds like a theoretical question then... Per your comment on the answer below, if you're loading 10MB 'sprites' you're doing it wrong.
No, there is nothing wrong about it if this can be achieved. That would reduce the number of calls by 100 every time the page is being called. That is a remarkable speed improvement even if everything is cached.
I see what you're trying to do, but in short, you can't. Counting pixels in JavaScript, if it possible at all (maybe with canvas? I don't think so though) would just be unreasonably resource-consuming. Loading all the images separately (i.e., not as one sprite), however, will give you exactly the effect you're looking for as a default on most browsers, albeit at the cost of more requests.
The solution? Use a Content Delivery Network (CDN), so the browser can fetch all 100 images at the same time, without necessarily putting the strain on your own server.
EDIT:
After some additional searching, I found what looks to be a solution here and is similar to a solution provided here. The basic idea is to make an AJAX request and monitor the progress.
If I'm understanding you correctly, you want to avoid that brief period of time that a page is loading (or after a even occurs) where images haven't finished transferring and don't yet appear where they should.
The problem I think you're going to run into (if this is a scenario where the page is loading) is that you're waiting for your placeholder image and the sprite to come across the wire. By the time your placeholder gets over, your sprite may have gotten there already or be milliseconds behind, and you haven't avoided the situation described above.
If you're dealing with a mouseover event or something similar where the sprite is requested for the first time, you can pre-load the sprite image by calling it via JavaScript when the page loads, so it'll already be cached and ready when the event fires.
I already have a theoretical solution. Before I start working on it, it would be nice if anyone can tell me if there is any major fault in my thinking.
The image is generated server-side, screenshot after screenshot. Therefore, after every screenshot merged into the sprite I can save the thumbnail size information to the database along with the corresponding entry.
Once user lands on the page, I will keep checking how many bytes of the sprite are loaded, loop through every entry that is pending to be displayed, check if the value is greater or equal to the entry "weight" and display or continue the loop appropriately.

Modifying flipbook jquery to load faster

I am using the Flipbook jquery plugin with a large png image sequence. I emailed the creator of the plugin and asked if there's any way to create some sort of "loader" or allow it to load in chunks and start playing after a certain amount of images are loaded. He responded with the following:
This should be possible and I was thinking of doing this but it wasn't needed at the time.
In the flip book code the shouldStartAnimation function determines if the animation should start by incrementing a counter and checking that counter against the total number of frames. When all the frames have been loaded the timer starts which flips the frames. This code could be changed so the timer starts after half the frames were loaded or something. It could also get really fancy and figure out how long each frame is taking to load and then guess how many frames it needs to let load before it can start playing the sequence so all the frames are loaded by the time it needs them.
Unfortunately I don't have time to make these changes myself, but feel free to modify this code for your needs :)
https://gist.github.com/719686
Unfortunately I don't know enough javascript to get this done, and I don't know exactly how much work this would be for someone who did. I am just hoping someone here might have some more helpful info or advice to help me figure this out (or, obviously, if this is easy enough for someone to just do, that would be amazing).
Add one more option default, the following, make sure to have proper "comas" in right places.
'loadbeforestart': 10, //start animation when 10 frames are loaded
And edit a variable in the following function, replace variable "end" with "loadbeforestart"
function shouldStartAnimation(){
//console.log('pre: '+imageName(i));
preloadCount += step;
if(preloadCount >= loadbeforestart){
setTimeout(flipImage, holdTime);
}
}
This should do the trick, I think*

Categories