使用 Pure JavaScript 在鼠标悬停时播放一系列动画 GIF 图片
Play series of Animated GIF Images on Mouse Hover using Pure JavaScript
我有一个要求,我有一个链接到一系列动画 gif 图片的 <image>
标签。
我想在 mouse over
状态下一个接一个地播放那些动画 (gif)(如播放列表)。然后在 mouse Out
我想 return 到一些原始 img 源(比如静态海报图像,等待用户 rollover
状态)。
请在下面找到我试过的伪代码:
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;
});
使用上述代码的挑战(修复):
1. 我希望 gif 图像仅在其动画完成后才被替换,但它在我使用 setInterval
时每次延迟计时器后都会被替换。
2. 在 mouse out
上它不是 return 原始图像。
3. 第一张图片也在 1 秒后加载(因为这是 setInterval
的速率)。
如果有什么方法可以实现,请告诉我。
更新:
- 问题 2 和 3 已解决。现在我面临的唯一问题是播放 gif 图片集。
要加载 GIF 持续时间,您可以使用 gify。然后在鼠标悬停时更改图像并设置一个超时函数,该函数使用当前 GIF 持续时间更改图像。
(function () {
var slideUrls = [
'https://media.giphy.com/media/9zXWAIcr6jycE/giphy.gif',
'https://media.giphy.com/media/3ohzdFhIALkXTBxPkQ/giphy.gif'
];
var originalUrl = 'http://via.placeholder.com/350x150';
// Loads the duration information for each GIF
var gifDurations = {};
function loadDurations(i) {
if (i >= slideUrls.length) return;
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", slideUrls[i]);
xhr.responseType = 'blob';
xhr.onload = function () {
blob = xhr.response;
var reader = new FileReader();
reader.onload = function (event) {
var gifInfo = gify.getInfo(reader.result);
gifDurations[slideUrls[i]] = gifInfo.duration;
loadDurations(i + 1)
}
reader.readAsArrayBuffer(blob);
}
xhr.send();
}
loadDurations(0);
var element = document.getElementById('id');
var timeout;
var currentSlide = 0;
function nextSlide() {
var url = slideUrls[currentSlide];
var duration = gifDurations[url];
element.setAttribute('src', slideUrls[currentSlide]);
currentSlide = (currentSlide + 1) % slideUrls.length;
timeout = setTimeout(function () {
nextSlide();
}, duration);
}
element.addEventListener('mouseover', function () {
nextSlide();
});
element.addEventListener('mouseout', function () {
clearTimeout(timeout);
element.src = originalUrl;
});
})();
使用jQuery .hover() with one static image and one .gif - JSFiddle
在写这篇文章之前先好好阅读一下thread。
$("#gifdiv").hover(
function () {
$(this).find("img").attr("src", "https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif");
}, function() {
$(this).find("img").attr("src", "https://lh4.googleusercontent.com/__LWblq_sBitgvSmldccaKsEqt0ADBGpPmYFsl3l0Jkxenqti4Jt05EN9EUJPDlHrM5DprN2-hrX3MM=w1680-h944");
}
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="gifdiv">
<img src="https://lh4.googleusercontent.com/__LWblq_sBitgvSmldccaKsEqt0ADBGpPmYFsl3l0Jkxenqti4Jt05EN9EUJPDlHrM5DprN2-hrX3MM=w1680-h944" class="static" />
</div>
很多小时后,我得到了我自己的问题的答案。
我得到了一个代码片段来获取 GIF 图像的持续时间。一旦我有了 GIF 图像的持续时间,我就可以在 GIF 图像的持续时间之后设置间隔。
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;
}
感谢 codepen,我从那里得到了解决方案:LINK
参考:
我有一个要求,我有一个链接到一系列动画 gif 图片的 <image>
标签。
我想在 mouse over
状态下一个接一个地播放那些动画 (gif)(如播放列表)。然后在 mouse Out
我想 return 到一些原始 img 源(比如静态海报图像,等待用户 rollover
状态)。
请在下面找到我试过的伪代码:
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;
});
使用上述代码的挑战(修复):
1. 我希望 gif 图像仅在其动画完成后才被替换,但它在我使用 setInterval
时每次延迟计时器后都会被替换。
2. 在 mouse out
上它不是 return 原始图像。
3. 第一张图片也在 1 秒后加载(因为这是 setInterval
的速率)。
如果有什么方法可以实现,请告诉我。
更新:
- 问题 2 和 3 已解决。现在我面临的唯一问题是播放 gif 图片集。
要加载 GIF 持续时间,您可以使用 gify。然后在鼠标悬停时更改图像并设置一个超时函数,该函数使用当前 GIF 持续时间更改图像。
(function () {
var slideUrls = [
'https://media.giphy.com/media/9zXWAIcr6jycE/giphy.gif',
'https://media.giphy.com/media/3ohzdFhIALkXTBxPkQ/giphy.gif'
];
var originalUrl = 'http://via.placeholder.com/350x150';
// Loads the duration information for each GIF
var gifDurations = {};
function loadDurations(i) {
if (i >= slideUrls.length) return;
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", slideUrls[i]);
xhr.responseType = 'blob';
xhr.onload = function () {
blob = xhr.response;
var reader = new FileReader();
reader.onload = function (event) {
var gifInfo = gify.getInfo(reader.result);
gifDurations[slideUrls[i]] = gifInfo.duration;
loadDurations(i + 1)
}
reader.readAsArrayBuffer(blob);
}
xhr.send();
}
loadDurations(0);
var element = document.getElementById('id');
var timeout;
var currentSlide = 0;
function nextSlide() {
var url = slideUrls[currentSlide];
var duration = gifDurations[url];
element.setAttribute('src', slideUrls[currentSlide]);
currentSlide = (currentSlide + 1) % slideUrls.length;
timeout = setTimeout(function () {
nextSlide();
}, duration);
}
element.addEventListener('mouseover', function () {
nextSlide();
});
element.addEventListener('mouseout', function () {
clearTimeout(timeout);
element.src = originalUrl;
});
})();
使用jQuery .hover() with one static image and one .gif - JSFiddle
在写这篇文章之前先好好阅读一下thread。
$("#gifdiv").hover(
function () {
$(this).find("img").attr("src", "https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif");
}, function() {
$(this).find("img").attr("src", "https://lh4.googleusercontent.com/__LWblq_sBitgvSmldccaKsEqt0ADBGpPmYFsl3l0Jkxenqti4Jt05EN9EUJPDlHrM5DprN2-hrX3MM=w1680-h944");
}
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="gifdiv">
<img src="https://lh4.googleusercontent.com/__LWblq_sBitgvSmldccaKsEqt0ADBGpPmYFsl3l0Jkxenqti4Jt05EN9EUJPDlHrM5DprN2-hrX3MM=w1680-h944" class="static" />
</div>
很多小时后,我得到了我自己的问题的答案。
我得到了一个代码片段来获取 GIF 图像的持续时间。一旦我有了 GIF 图像的持续时间,我就可以在 GIF 图像的持续时间之后设置间隔。
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;
}
感谢 codepen,我从那里得到了解决方案:LINK
参考: