I have a requirement where I have an <image>
tag linked to a series of animated gif images.
I want to play those animations (gif) on mouse over
state, one after another (like a playlist). Then on mouse Out
I want to return to some original img source (like a static poster image, waiting for user rollover
state).
Please find pseudo code below that I have tried:
function nextSlide() {
document.getElementsByTagName('img').setAttribute('src', slides[currentSlide]);
currentSlide = (currentSlide + 1) % slides.length;
}
document.getElementsByTagName('img').addEventListner('mouseover',function(){
slides = gifImages;
var slideInterval = setInterval(nextSlide,1000);
});
document.getElementsByTagName('img').addEventListener('mouseout', function(){
document.getElementsByTagName('img').src = originalImage;
});
Challenges (to fix) from using above code:
1. I want gif image to be replaced only after its animation is completed, but its getting replaced after every delay of timer as I am using setInterval
.
2. On mouse out
it is not returning to original image.
3. First image is also being loaded after 1 sec (since that's rate of setInterval
).
Please let me know if there is any way to achieve this.
Update:
After lot of hours I got answer to my own question.
I got a code snippet to get duration of GIF Image. And once I have duration of GIF image I can set interval after duration of GIF images.
function getGIF(url) {
function downloadFile(url, success) {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (success) {
success(xhr.response);
}
const file = new Blob([xhr.response], {type:'image/jpeg'});
}
};
xhr.send(null);
}
downloadFile(url, function (data) {
let d = new Uint8Array(data);
let bin = null;
let duration = 0;
for (let i = 0; i < d.length; i++) {
bin += String.fromCharCode(d[i]);
// Find a Graphic Control Extension hex(21F904__ ____ __00)
if (d[i] === 0x21 &&
d[i + 1] === 0xF9 &&
d[i + 2] === 0x04 &&
d[i + 7] === 0x00) {
// Swap 5th and 6th bytes to get the delay per frame
let delay = (d[i + 5] << 8) | (d[i + 4] & 0xFF);
// Should be aware browsers have a minimum frame delay
// e.g. 6ms for IE, 2ms modern browsers (50fps)
duration += delay < 2 ? 10 : delay;
}
}
});
return duration;
}
Thanks to codepen from where I got the solution: LINK
REFERENCE: