重播GIF动画/点击重新加载GIF

3

我有一个大的GIF动画,并且我让它显示一个加载图标,直到GIF加载完成为止。一旦加载完成,GIF就会显示出来。效果很好,但是我想添加一个“重播”按钮来触发GIF重新播放(重新加载)。

加载和GIF的代码:

HTML

<div id="loader" class="loading img-center"></div>

CSS

#loader {
 width: 600px;
 height: 450px;
 margin: auto; 
}

#loader.loading {
  background: url(/Images/ajax-loader.gif) no-repeat center center;
  width:32px;
  margin:auto ; 
}

JS

var $j = jQuery.noConflict();
$j(function () {
  var img = new Image();
  $j(img)
   .load(function () { 
     $j(this).hide();
     $j('#loader') 
      .removeClass('loading')
      .append(this);

  $j(this).fadeIn();
   })
 .error(function () {
   })
 .attr('src', '/2012/images/august/sailboat.gif');
});

以上代码工作正常。现在是“Replay”或“Reload”代码无法运行的问题: HTML
<a id="refresh" href="#"> Replay Animation </a>

JS

$j(function() {
  $j("#refresh").click(function() {
     $j("#loader").load("/2012/images/august/sailboat.gif")
  })
})

我知道JS代码中存在一些错误,但由于我对JS技能的不足,我不知道应该做什么或尝试什么。非常感谢任何帮助或建议!

谢谢!


为什么要费这么大的劲,不如直接编辑实际的gif图像使其重复。 - elclanrs
@elclanrs - 因为 GIF 中有文本,我希望用户可以控制是否要重新播放。 - L84
3个回答

4

请检查以下内容:

$j("#refresh").click(function() {
  $j("#loader").find('img').attr("src", "/2012/images/august/sailboat.gif");
});

在您之前的代码中,您将图像附加在#loader中,因此,$('#loader').load(..)将不起作用。请在#loader中查找图像,然后更改该图像的src


明白了!我把代码放在<head>里了,现在需要放到HTML的<body>标签下面。 - L84

2
您也可以添加时间戳,以避免需要时从缓存中加载图片:
$j("#refresh").click(function() {
  var timestamp = new Date().getTime();
  $j('#loader').find('img').attr('src', '/2012/images/august/sailboat.gif'+'?'+timestamp);
});

1
避免缓存会使加载指示器毫无意义。它只需要重新下载所有内容。 - Eric

0
问题是11年前提出的,但至今仍没有一个通用的解决方案。
有多种方法可以解决这个问题,但没有一种是最优的,取决于您的需求,其中一种可能比其他方法更好。就记录而言,当我说gif时,我指的是所有动画图像格式,包括.gif、.webp、.apng和.avif。
一种方法是将您的gif转换为mp4文件格式,这将为您提供更多的控制API,并且通常会得到相同媒体的较小文件。但请注意:
A)自己提供gif或者能够访问视频格式以显示转换后的版本。
B)要么转换没有透明部分的gif,要么接受与页面背景相同的背景。
另一种提到的方法是通过重置img元素的src属性或附加查询字符串来更改src属性。在某些格式/浏览器组合中,重置可能无效,在某些情况下,它会重置DOM中所有图像的所有实例,尽管很可能会命中缓存,但这并不确定,重新加载意味着糟糕的用户体验。
追加查询字符串将有助于确保重置发生,并且附加的元素只受到影响,但这意味着缓存将始终被绕过,除了给服务器带来更多压力和带宽使用外,对于客户端而言,一个速度较慢、数据使用量较高的网站并不是我们所追求的。
如果转换为mp4不可行,我脑海中浮现的解决方案是追加查询字符串,同时利用服务工作器缓存。
下面的代码来自MDN,用于缓存请求。
const putInCache = async (request, response) => {
    const cache = await caches.open("v1");
    await cache.put(request, response);
};

const cacheFirst = async ({ request, fallbackUrl }) => {
    // First try to get the resource from the cache
    const responseFromCache = await caches.match(request);
    if (responseFromCache) {
        return responseFromCache;
    }

    // Next try to get the resource from the network
    try {
        const responseFromNetwork = await fetch(request);
        // response may be used only once
        // we need to save clone to put one copy in cache
        // and serve second one
        putInCache(request, responseFromNetwork.clone());
        return responseFromNetwork;
    } catch (error) {
        const fallbackResponse = await caches.match(fallbackUrl);
        if (fallbackResponse) {
            return fallbackResponse;
        }
        // when even the fallback response is not available,
        // there is nothing we can do, but we must always
        // return a Response object
        return new Response("Network error happened", {
            status: 408,
            headers: { "Content-Type": "text/plain" },
        });
    }
};

self.addEventListener("fetch", (event) => {
    event.respondWith(
        cacheFirst({
            request: event.request
        })
    );
});


但是我们需要在事件监听器中进行一些更改。
self.addEventListener("fetch", (event) => {
    let url = event.request.url
    if (url.includes('reqcacheqs')) {
        url = url.replace(/reqcacheqs=([^&]*)&?/, '')
        const request = event.request
        request.url = url
        event.respondWith(
            cacheFirst({
                request: event.request
            })
        );
    }
});


在这里,我们基本上忽略了服务工作者中的reqcacheqs,并且可以在我们的img元素中更改它的值,而不必担心反复向服务器发出请求。我还没有测试过这段代码,可能会有一些错误,但基本思想如所示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接