Перезапустить анимированный GIF в качестве фона-изображение
можно ли перезапустить анимированный GIF, используемый как background-image
?
рассмотрим этот HTML:
<div id="face">
<div id="eyes"></eyes>
</div>
и этого стиля:
#eyes.blink {
background-image:url('blink.gif');
}
Я бы blink.gif
анимация для воспроизведения каждый раз, когда я добавляю класс blink
to #eyes
, а не только в первый раз.
Я ожидал, что это сработает:
function startBlink() {
$('#eyes').addClass('blink');
}
function stopBlink() {
$('#eyes').removeClass('blink');
}
проблема в том, что Firefox и браузер WebKit не воспроизводят анимацию GIF-изображений после того, как она была воспроизведена один раз. Добавление / удаление класса blink работает только в первый раз.
8 ответов
вы можете получить анимированный gif для воспроизведения, перезагрузив его. Это не идеально подходит для полосы пропускания, особенно если ваше изображение большое, но это заставит перезапустить анимацию.
в моем примере я добавляю и удаляю его onclick
of <div id="animated">
:
$('#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"});
}
})
демо в действии.
Я нашел вы также можете добавить ?+Math.random()
до конца изображения src, и он перезагрузит .файл gif.
Я объединил несколько частей решения, чтобы сделать одно целое решение, которое решает (надеюсь) все проблемы:
- определите URL фонового изображения элемента (из css
background-image
) - запустите перезапуск для этого изображения без перезагрузки его из интернета
- перезапуск его во всех местах (не касаясь каждого отдельно)
- убедитесь, что цель перекрашена без артефактов после перезапуска анимация
в моем решении я создаю вспомогательные изображения, которые добавляются в тело, но скрыты таким образом, чтобы они по-прежнему визуализируются браузером, но не будут взаимодействовать со страницей визуально с помощью position: absolute; left: -5000px;
.
ссылка на наши вспомогательные изображения кэшируется в resetHelperImages
таким образом, мы можем использовать их для того же изображения в последующих вызовах.
Я использую jQuery для своего примера, но он также может быть адаптирован для работы без jQuery.
протестировано в: Chrome (Версия 43.0.2357.130 m)
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>
вы рассматривали использование одного и того же изображения, дважды называемого 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');
}
}
просто потому, что мне все еще нужно это время от времени, я подумал, что чистая функция 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 изображения. Это удобно если вы когда-нибудь измените фактическую ссылку изображения для данного идентификатора, потому что вам не нужно помнить об изменении вызовов resetGiF ().
--Нико
существует альтернатива, которая не перезагружает GIF каждый раз и не тратит пропускную способность.
Он включает в себя хранение GIF как Base64 в памяти (обход кэша браузера) и использует API FileReader (который, кажется,поддерживается во всех современных браузерах). Обратите внимание, что загрузка изображений таким образом зависит от политики кросс-происхождения (в отличие от решений перезагрузки изображений.)
обновление: кэширование браузера становится умнее о кэшировании фона URI данных изображения, в результате чего анимация не запускается. Я обнаружил, что теперь мне нужно добавить случайную строку кэширования в url-адрес данных (который согласно Схема DataURI, следует считать необязательным атрибутом. Протестировано в Chrome & IE Edge.)
увидеть его в действии:http://jsfiddle.net/jcward/nknLrtzL/10/
вот как это работает. Эта функция загружает изображения в 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
// Slip in a cache busting random number to the data URI attributes
$div.css({backgroundImage: "url("+img_base64.replace("image/gif","image/gif;rnd="+Math.random())+")"});
спасибо ответ на toDataURL
функция (с исправлением для IE11.)
по какой-то причине это работает:
// 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';
для этого требуется добавить на страницу фактический элемент image DOM, но вы можете скрыть его с помощью visibility: hidden
. Это не требуется, чтобы изображение было загружено по сети несколько раз.
Я тестировал это только в Firefox и Chrome. Не уверен в других браузерах.
о ответ сообщение от Фредерик Лайтенбергер, Я нашел, что это работает чудесно.
однако он ломается, если ваше фоновое изображение имеет несколько слоистых частей, например:
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 фонового изображения.
Я бы добавил Это в качестве комментария к связан ответа, но я нуб без репутации, поэтому был заблокирован от этого. Те адекваты рэп может понадобиться добавить строку для ответа.