2011-09-27 94 views
16

是否可以重新启动动画GIF,用作background-image重新启动动画GIF作为背景图

考虑这个HTML:

<div id="face"> 
    <div id="eyes"></eyes> 
</div> 

而且这一款式:

#eyes.blink { 
    background-image:url('blink.gif'); 
} 

我想blink.gif动画打我每次添加类blink#eyes,不只是第一次的时间。

我预计这个工作:

function startBlink() { 
    $('#eyes').addClass('blink'); 
} 

function stopBlink() { 
    $('#eyes').removeClass('blink'); 
} 

的问题是,Firefox和WebKit浏览器都不会再次播放背景图像的GIF动画一旦播放一次。添加/删除类闪烁只能在第一次使用。

+0

不要GIF动画循环? –

+0

@NoufalIbrahim只有当它们被设置为循环。 – JJJ

+1

@Noufal Ibrahim - 他们*可以做到,它取决于图像中设置的循环选项。 – Quentin

回答

14

您可以通过重新载入动画gif来重放它。这对带宽并不理想,特别是如果图像很大,但会强制重新启动动画。

在我的例子,我添加和删除它的<div id="animated">onclick

$('#animated').click(function() { 

    /* Reference to the clicked element and toggle the .go class */ 
    var $div = $(this); 
    $div.toggleClass('go'); 

    /* Start the animated gif */ 
    if ($div.hasClass('go')) { 

     /* Create an <img> element and give it the animated gif as a src. To 
      force a reload we add a date parameter to the URL */ 
     var img = document.createElement('img'); 
     img.src = "http://yoursite.com/animated.gif?p" + new Date().getTime(); 

     /* Once the image has loaded, set it as the background-image */ 
     $(img).load(function(){ 
      $div.css({backgroundImage: "url("+img.src+")"}); 
     }); 

    /* Remove the background-image */   
    } else { 
     $div.css({backgroundImage: "none"}); 
    } 
}) 

在行动Demo of it

+0

为什么你添加随机数到文件路径?趋于落后** ? - 只需重新设置'src'就足以让动画重启。 http://jsfiddle.net/Lqx2V/ – c69

+1

@ c69它强制它不使用浏览器缓存。没有这个Webkit就不会重新启动动画。 – Pat

+2

omg .. webkit sux then :( – c69

1

你有没有考虑过两次使用相同的图像blink.gif和blink2.gif,为它们添加两个类并在类之间切换?

<div id="face"> 
    <div id="eyes"></eyes> 
</div> 

.blink { 
    background-image:url('blink.gif'); 
} 

.blink2 { 
    background-image:url('blink2.gif'); 
} 

function MakeBlink() 
{ 
    if ($('#eyes').hasClass('blink')) 
    { 
     $('#eyes').removeClass('blink').addClass('blink2'); 
    } else 
    { 
    $('#eyes').removeClass('blink2').addClass('blink'); 
    } 
} 
+0

这将是两帧动画(“眨眼”)的方式。点击键盘上的Esc按钮即可取消Gif动画。 – Lekensteyn

+0

是否真的需要有不同的图像?我无法看到为什么* $('#eyes')。removeClass('blink')。addClass('blink'); *不起作用的原因 – Ivan

+0

@Ivan - 据推测,OP希望眼睛闪烁,眼睑闭合,而不是消失。 – Quentin

5

我发现你也可以添加一个?+Math.random()到图片src的结尾,它会重新加载.gif文件。

+0

尼斯!良好的建议,工程!:) – podeig

+2

更好,你可以将'#'+ Math.random()添加到URL中,然后大概浏览器不必重新加载它。我已经在Chrome中测试了它,并且它可以工作(它从缓存中检索)。 – Abram

+2

@Abram ,在URL中添加'#'而不是'?'似乎不再有效FWIW –

0

出于某种原因,这个工程:

// Append the image to the page 
var i = new Image(); 
i.src = 'some.gif'; 
document.body.appendChild(i); 

// Now execute this line and the gif will restart 
// (anywhere it appears on the page, including CSS backgrounds) 
i.src = 'some.gif'; 

这需要附加到页面中的实际图像的DOM元素,但你可以visibility: hidden隐藏它。这要求图像通过网络多次下载。

我只在Firefox和Chrome中测试过。不确定其他浏览器。

1

仅仅因为我现在仍然需要这个东西,我认为我使用的纯JS功能可能对别人有帮助。这是一个纯JS的重新启动GIF动画的方式,无需重新加载。您可以通过链接和/或文档加载事件调用此功能。

<img id="img3" src="../_Images/animated.gif"> 

<a onClick="resetGif('img3')">reset gif3</a> 

<script type="text/javascript"> 

// reset an animated gif to start at first image without reloading it from server. 
// Note: if you have the same image on the page more than ones, they all reset. 
function resetGif(id) { 
    var img = document.getElementById(id); 
    var imageUrl = img.src; 
    img.src = ""; 
    img.src = imageUrl; 
}; 

</script> 

在某些浏览器上,您只需要将img.src重置为自身并且工作正常。在IE上,您需要清除它,然后重置它。这resetGif()从图像ID中挑选图像名称。如果您更改给定ID的实际图像链接,这很方便,因为您不必记住更改resetGiF()调用。

--Nico

3

我结合溶液的几部分,使一个整体解决方案,解决了(希望)的所有问题:

  • 确定的元件(的背景图像的URL从CSS background-image
  • 触发该图像而无需从网络
  • 重装它在所有的地方重新启动它重新启动(不接触每个单独)
  • 确保目标被重新启动动画

在我的解决方案后,没有任何瑕疵粉刷我创建了被添加到身体,但隐藏的,所以他们仍然在浏览器呈现,但不会进行交互的辅助图像与页面视觉使用position: absolute; left: -5000px;

对我们的帮助图片的引用被缓存在resetHelperImages中,因此我们可以在随后的调用中重用它们以用于相同的图像。

我为我的例子使用jQuery,但它可以适应没有jQuery的工作。

在测试:铬(版本43.0.2357.130米)

var resetHelperImages = {}; 
 

 
function restartAnimation(elem) { 
 
    elem = $(elem); 
 
    for (var i = 0; i < elem.length; i++) { 
 
    var element = elem[i]; 
 
    // code part from: http://stackoverflow.com/a/14013171/1520422 
 
    var style = element.currentStyle || window.getComputedStyle(element, false); 
 
    // var bgImg = style.backgroundImage.slice(4, -1).replace(/"/g, ''); 
 
    var bgImg = style.backgroundImage.match(/url\(([^\)]+)\)/)[1].replace(/"/g, ''); 
 
    // edit: Suggestion from user71738 to handle background-images with additional settings 
 

 
    var helper = resetHelperImages[bgImg]; // we cache our image instances 
 
    if (!helper) { 
 
     helper = $('<img>') 
 
     .attr('src', bgImg) 
 
     .css({ 
 
      position: 'absolute', 
 
      left: '-5000px' 
 
     }) // make it invisible, but still force the browser to render/load it 
 
     .appendTo('body')[0]; 
 
     resetHelperImages[bgImg] = helper; 
 
     setTimeout(function() { 
 
     helper.src = bgImg; 
 
     }, 10); 
 
     // the first call does not seem to work immediately (like the rest, when called later) 
 
     // i tried different delays: 0 & 1 don't work. With 10 or 100 it was ok. 
 
     // But maybe it depends on the image download time. 
 
    } else { 
 
     // code part from: http://stackoverflow.com/a/21012986/1520422 
 
     helper.src = bgImg; 
 
    } 
 
    } 
 
    // force repaint - otherwise it has weird artefacts (in chrome at least) 
 
    // code part from: http://stackoverflow.com/a/29946331/1520422 
 
    elem.css("opacity", .99); 
 
    setTimeout(function() { 
 
    elem.css("opacity", 1); 
 
    }, 20); 
 
}
.myBgImageClass { 
 
    background-image: url('http://i410.photobucket.com/albums/pp184/OllieMarchant/Countup.gif'); 
 
    width: 100px; 
 
    height: 150px; 
 
    background-size: 100%; 
 
    background-repeat: no-repeat; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<div class="myBgImageClass"></div> 
 
<button onclick="restartAnimation($('.myBgImageClass'))">restart</button>

+0

在ie中不起作用。 – jnkb

+0

@jnkb是的,你是对的,它在IE中不起作用。也许所有浏览器的通用解决方案都是下载和缓存图像的原始数据,然后创建一个'data:'-url来重新开始动画。也许'数据:'-url缓存失效......可能吗? –

0

有不重新加载每次和浪费带宽的GIF的替代方案。

它涉及在内存中存储GIF作为Base64(绕过浏览器缓存),并使用FileReader API(似乎是supported in all modern browsers)。需要注意的是加载图像这种方式受到跨域政策

看到它在行动(不像形象重装的解决方案。):http://jsfiddle.net/jcward/nknLrtzL/2/

下面是它如何工作的。此函数将图像作为Base64编码的字符串加载。

function toDataUrl(url, callback) { 
    var xhr = new XMLHttpRequest(); 
    xhr.onload = function() { 
    var reader = new FileReader(); 
    reader.onloadend = function() { 
     callback(reader.result); 
    } 
    reader.readAsDataURL(xhr.response); 
    }; 
    xhr.open('GET', url); 
    xhr.responseType = 'blob'; // IE11, set responseType must come after .open() 
    xhr.send(); 
} 

然后,你要重新启动的GIF动画任何时候,background-image属性更改为none,然后以base64字符串(在某些浏览器,你需要重新添加子触发更新没有的setTimeout ):

$div.css({backgroundImage: "none"}); 
$div.parent().add($div); // Some browsers need this to restart the anim 
$div.css({backgroundImage: "url("+img_base64+")"}); 

在一些情况下,触发

由于this answertoDataURL函数(修正为IE11)

。 210
0

关于this answer发布者Frederic Leitenberger,我发现它工作非常好。

然而,它打破了,如果你的背景图片有多种,分层的部分,像这样:

background-image: url(https://upload.wikimedia.org/wikipedia/commons/5/53/Google_%22G%22_Logo.svg), 
    radial-gradient(ellipse at center, 
     rgba(255,255,255,1) 0%, 
     rgba(255,255,255,1) 50%, 
     rgba(255,255,255,0) 80%); 

为了绕过这个限制,我修改了发现背景图像的URL,像这样的一行:

var bgImg = style.backgroundImage.match(/url\(([^\)]+)\)/)[1].replace(/"/g, ''); 

这使用正则表达式来提取背景图像的URL部分。

我会添加这个作为linked answer的评论,但我是一个没有声望的noob,所以被阻止这样做。那些有足够的代表可能想要添加行到实际的答案。

+0

我将您的改进添加到了我的解决方案中。谢谢! –