在不重新加载图像的情况下从 JavaScript 重新启动动画 GIF

IT技术 javascript jquery gif animated-gif
2021-02-20 15:53:49

我正在使用动画 GIF 创建动画幻灯片。我正在从一个动画淡入到下一个。问题是:我发现确保 GIF 从第一帧开始动画的唯一方法是每次显示时重新加载它。每个 GIF 大约 200KB,这对于连续幻灯片放映来说是太多的带宽。

这是我当前的代码。imgnextimg<div>包含单个<img>每个的标签nextimg_img<img>下一张要显示的图片对应标签。

var tmp = nextimg_img.attr('src');
nextimg_img.attr('src', '');
setTimeout(function() { nextimg_img.attr('src', tmp); }, 0);
img.fadeOut('slow');
nextimg.fadeIn('slow');

这个想法是它将src下一个图像属性设置'',然后将其设置回要显示的 GIF 的源。

这有效——它从头开始重新启动动画——但每次显示 GIF 时似乎都会重新下载它们。

编辑:这是一个循环幻灯片,我试图避免在第二次/第三次/后续时间显示时从网上重新加载 GIF。

4个回答

您应该将图像预加载到代码中。

var image = new Image();
image.src = "path";

当你想使用:

nextimg_img.attr('src', image.src);

然后,当您交换 src 时,只需从预加载的图像对象中交换即可。这应该可以避免重新下载。

那会从头开始播放 GIF 动画吗?
2021-04-21 15:53:49
最后,这是一个显示解决方法的小提琴,随机伪造的查询字符串总是会导致重新下载。无论大小:jsfiddle.net/xLh5wsxd/3
2021-04-22 15:53:49
我不明白为什么它不会。正如我想象的那样,动画在屏幕上显示之前不会真正开始。但老实说,我之前没有尝试过,所以我不能 100% 肯定地说。
2021-05-04 15:53:49
啊,你说得对——我遗漏了一个细节。这是一个循环幻灯片。所以当 GIF 再次出现时,除非我重新加载它们,否则它们的动画已经完成了一半。
2021-05-06 15:53:49
那很有意思。不确定这是否会影响这个。但是,如果您隐藏图像与从 dom 中删除它们会有所不同。我会说在你淡出它们之后,你应该删除对象,以便从 dom 中删除它。然后当您使用预加载的图像重新加载图像时,它应该无关紧要。
2021-05-12 15:53:49
// reset a gif in javascript
img.src = "your_image_url.gif"+"?a="+Math.random();

多田!

请注意,每次都会下载 GIF,因此请将其保存为一个小文件。

大声笑,这正是OP 试图避免的。 (“...无需重新加载图像”)
2021-04-26 15:53:49
哈哈哈哈我不知道我在想什么……你是对的!
2021-04-27 15:53:49

这是一个单循环 5 帧 GIF(例如,repeat=1)。

只要它是页面上该 GIF 的唯一实例,就可以根据需要重新启动(手动或定时器等)。如果它不是唯一的,则所有实例将一起重新启动。

const gif=document.getElementById('gif');

function restartGIF(){
   gif.src=gif.getAttribute('src');
}

function startTimer(){
  gif.src=gif.getAttribute('src');
  setTimeout(function(){ restartGIF() }, 10000);
}
<button onclick="restartGIF()">restart gif</button>
<br>
<button onclick="startTimer()">start every 10s</button>
<br>
<img id='gif' src='https://i.stack.imgur.com/VBKe6.gif'>

(基于 Spinon 接受的答案。)

由于Cross-Origin 限制下一个答案仅当您的.gif图像位于您的服务器或提供Access-Control-Allow-Origin: *标头响应的服务器上时才有效

我使用内置fetch()将 gif 下载到内存 blob。然后这个 blob 用于.src在您需要重新启动动画时更新img 元素的属性。由于 blob 保存在内存中,因此不会重新下载。同样要重新启动动画,您只需要再次更新.src具有相同值的属性。

如果fetch()目标浏览器不支持,则XMLHttpRequest可以使用 goodold。URL.createObjectURL()可以命名不同,然后可以使用像这里这样的包装器

下面的代码也可以在 jsfiddle上测试

<input id="btn" type="button" value="ReStart">
<img id="img" height="150">
<script>
    document.addEventListener('DOMContentLoaded', ()=>{
        // fetch works only with urls on same server or servers that provide header "Access-Control-Allow-Origin".
        fetch('https://api-project-268277679120.appspot.com/h80bm5vc4iw7?url=https://i.stack.imgur.com/SkGeh.gif')
            .then(r=>r.blob())
            .then(b=>URL.createObjectURL(b))
            .then(u=>{
                document.getElementById('img').src = u;
                document.getElementById('btn').onclick = ()=>{
                    document.getElementById('img').src = u;
                };
            });
    });
</script>