Asynchronously playing multiple <img> tags with the same animated GIF
I have many <img> tags on a single HTML page, some of which have the same animated GIF file. The src URL is set dynamically using JavaScript, but with my code the same characters are played again or the next characters are displayed immediately with the last frame.
Idea: This is for an art project. After entering some text, the characters are displayed in a special font, and some transition is carried out by the character to the character (one after another), which I can only implement using animated GIFs. The text is split into individual characters, and the <img> tags are created as follows:
<!-- delivered HTML at page load --> <img src="initial/f.png"> <!-- I used to PNG here to outline --> <img src="initial/o.png"> <!-- the animation is NOT set a first --> <img src="initial/o.png"> When the animation starts, the first <img> URL is set to transition/f.gif . Only after he has finished the game (determined by time) is the 2nd image set, etc.
<!-- while 2nd animation is running --> <img src="transition/f.gif"> <!-- already finished, displays last frame --> <img src="transition/o.gif"> <!-- being animated right now --> <img src="transition/o.png"> <!-- will be reset to o.gif in next step --> Problem I cannot solve: After o.gif from the example has been played, the animation of the next O does not work correctly.
I tried to define a class for each character and assign the image as background-image . After any appearance of the character played any subsequent occurrences of the same letter, the last frame (final state) of this GIF was displayed.
I also tried setting the src attribute directly using JavaScript, but when the second letter O is set like this, the first animation with the letter O restarts synchronously. But he must remain on the last frame.
Since the HTML page should also work on the local file system, I think that arguments like o.gif?random=argument to bypass the caching mechanism will not work or will have no effect (maybe on some computers the testing itself will not falsify) .
You need to create unique URLs for images, so the browser will always reload letters instead of using cached ones. You could achieve this, for example, with a little php that outputs the correct gif for the parameter.
<img src="gif_printer.php?letter=o&t=1234567"> The t parameter must be a timestamp when creating the img tag. This gives enough difference to reload.
In php set headers, limit / disable caching and output type for gif and just pour image content into standard output.
The timestamp parameter and cache control headers should be sufficient for the browser to reload the evert letter.
If your test environment does not respond correctly, you can try the htaccess solution, but for this you need to use a web server (and this may already be enough for the previous solution to work).
This means rewriting any url in images / [az] .gif into images /[azโ .gif, so just remove the extra noise except the first letter and extension.
Do not use GIFs, but image sequences and Javascript. I put together a crude instance of a Javascript object that does just that:
<html> <head> <script> function Animator(target, frames, delay) { var _this = this; // array of frames (image objects) var f = []; // a reference to the object where our frames will appear var t = document.getElementById(target); // the interval variable. Used to stop and start var t_loop; // create a new image element and remember it var img_el = document.createElement("img"); // current frame var c_frame = 0; t.innerHTML = ""; t.appendChild(img_el); var i, img; // preload immediately for(i = 0; i < frames.length; i++) { img = new Image(); img.src = frames[i]; f.push(img); } this.play = function() { t_loop = window.setInterval(_this.frame, delay); } this.stop = function() { clearInterval(t_loop); } this.gotoFrame = function(frame) { c_frame = frame; _this.frame(); } this.frame = function() { img_el.src = f[c_frame].src; c_frame++; if(c_frame >= f.length) { c_frame = 0; } } } function loaded() { var quip_frames = [ "http://www.abcteach.com/images/abma_thumb.gif", "http://www.abcteach.com/images/abcu_thumb.gif", "http://www.abcteach.com/images/zbma_thumb.gif", "http://www.abcteach.com/images/zbcu_thumb.gif", "http://www.abcteach.com/images/dnma_thumb.gif", "http://www.abcteach.com/images/dncu_thumb.gif" ]; var anim1 = new Animator("target1", quip_frames, 100); var anim2 = new Animator("target2", quip_frames, 100); var anim3 = new Animator("target3", quip_frames, 100); anim1.play(); window.setTimeout(anim2.play, 200); window.setTimeout(anim3.play, 300); } </script> </head> <body onload="loaded()"> <div id="target1"> </div> <div id="target2"> </div> <div id="target3"> </div> </body> </html> thanks to ABCTeach for images
The object loads the images in a loop, stores them in an array, and then simply using setInterval() collapses the frames at the desired speed. When the page loads, it makes three of these objects, each of which points to a different DIV, but each with the same frames. Then he tells everyone to play with a different delay (the first immediately, the second after 200 ms, the third after 300 ms). In your case, you will create one array for each letter that you will use:
var A = [*array of URLs to images of the letter A*]; var B = [*array of URLs to images of the letter B*]; ... Then create a new Animator object for each div on your page by sending it an appropriate array of letters:
var letter_so_and_so = new Animator("div_so_and_so", A, 100); var letter_this_and_that = new Animator("div_this_and_that", B, 100); var another_letter = new Animator("another_div", B, 100); Finally, give each one either the start of the offset, or call their Animator.gotoFrame(f) method to run them on different frames (don't forget Animator.play() !).
Try to accept something like this in your code, I think you will find that it works wonders.