【问题标题】:Restart an animated GIF from JavaScript without reloading the image从 JavaScript 重新启动动画 GIF 而不重新加载图像
【发布时间】:2011-03-12 15:20:10
【问题描述】:

我正在使用动画 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。

【问题讨论】:

  • (老问题但是....) 如果我理解正确,您只是希望 GIF 无限循环?如果是这样,您不需要以编程方式进行;您只需将 gif 的“重复”值设置为 0 即可“无限期地”重复。您可以使用ezGIF.com 之类的在线工具来执行此操作(上传 gif,然后单击“帧”将“循环”值更改为 0)。如果这不是问题,我还添加了一个答案 below 关于如何使用 JS 重新启动 gif。
  • 这不是我在这个问题中要问的。我在问如何在显示 GIF 动画时从头开始。

标签: javascript jquery gif animated-gif


【解决方案1】:

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

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

当你想使用时:

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

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

【讨论】:

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

多田!

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

【讨论】:

  • 大声笑,这正是 OP 试图避免的。 ("...不重新加载图像")
  • 哈哈哈我不知道我在想什么……你说得对!
【解决方案3】:

这是一个单循环 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 接受的answer。)

【讨论】:

    【解决方案4】:

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

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

    如果目标浏览器不支持fetch(),则可以使用旧的XMLHttpRequest。此外,URL.createObjectURL() 的命名可能不同,然后可以使用包装器 like here

    下面的代码也可以测试on 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>

    【讨论】:

      猜你喜欢
      • 2013-11-18
      • 2018-10-13
      • 1970-01-01
      • 2011-11-25
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 2010-09-08
      相关资源
      最近更新 更多