2012-05-24 13 views
14

El título se explica por sí mismo, pero proporcionaré una vista paso a paso sobre el asunto. Espero no ser el primero en haber notado este error (aparentemente) en Webkit/Chrome.Forma correcta de restablecer una animación GIF con visualización: ninguna en Chrome

Quiero reiniciar una animación GIF. Todos los ejemplos que he visto hasta ahora simplemente configuran el src de la imagen o lo configuran en una cadena vacía seguido por el src original nuevamente.

Echa un vistazo a este JSFiddle de referencia. El GIF se restablece perfectamente en IE, Firefox y Chrome. El problema que tengo es cuando la imagen tiene display:none en Google Chrome solamente.

Verificar esto JSFiddle. El GIF se restablece bien en IE y Firefox antes de mostrarse en la página, ¡pero Chrome simplemente se niega a restablecer su animación!

Lo que he probado hasta ahora:

  • Ajuste del src a sí misma como en el violín, no funciona en Chrome.
  • Establecer el src en una cadena vacía y restablecerlo al valor predeterminado, tampoco funciona.
  • Poner una envoltura alrededor de la imagen, vaciar el contenedor a través de .html('') y volver a poner la imagen en su interior, tampoco funciona.
  • Cambiando el display de la imagen a través de .show() o .fadeIn() justo antes de configurar el src tampoco funciona.

El única solución la que he encontrado hasta ahora es mantener la imagen con su defecto display y manipular a través de .animate() ing ing y .css() la opacidad, la altura y la visibilidad cuando sea necesario para simular un comportamiento display:none.

La razón principal (contexto) de esta pregunta es que quería restablecer un GIF de cargador ajax justo antes de desvanecerlo en la página.

Así que mi pregunta es, ¿existe una forma adecuada de restablecer la animación de una imagen GIF (que evita el "error" de Chrome display:none) o es realmente un error?

(ps. Es posible cambiar el GIF de los violines para una animación GIF más apropiado/tiempo para la prueba)

+0

me funcionó una solución completa. Vea aquí: http://stackoverflow.com/a/31093916/1520422 –

Respuesta

24

ofertas Chrome con cambios en el estilo diferente que otros navegadores.

En Chrome, cuando llama al .show() sin argumentos, el elemento no se muestra inmediatamente justo donde lo llama. En su lugar, Chrome pone en cola la aplicación del nuevo estilo para la ejecución después de evaluar el fragmento actual de JavaScript; mientras que otros navegadores aplicarían el nuevo cambio de estilo inmediatamente. .attr(), sin embargo, no se pone en cola. Por lo tanto, intenta establecer el src cuando el elemento aún no está visible según Chrome, y Chrome no hará nada cuando el original src y el nuevo src sean iguales.

su lugar, lo que necesita hacer es asegurarse de jQuery establece el srcdespués de aplicardisplay:block. Puede hacer uso de setTimeout para lograr este efecto:

var src = 'http://i.imgur.com/JfkmXjG.gif'; 
$(document).ready(function(){ 
    var $img = $('img'); 
    $('#target').toggle(
     function(){ 
      var timeout = 0; // no delay 
      $img.show(); 
      setTimeout(function() { 
       $img.attr('src', src); 
      }, timeout); 
     }, 
     function(){ 
      $img.hide(); 
     } 
    ); 
}); 

Esto asegura que src se establece después de display:block se ha aplicado al elemento.

La razón por la que esto funciona es porque setTimeout en cola la función para su ejecución tarde (sin importar el tiempo tarde es), por lo que la función ya no es considerado como parte de la corriente "trozo" de JavaScript, y proporciona un hueco para Chrome para representar y aplicar el display:block primero, lo que hace que el elemento sea visible antes de que se establezca su atributo src.

Demostración: http://jsfiddle.net/F8Q44/19/

Gracias a Shoky en #jquery de IRC freenode para proporcionar una respuesta más simple.


O bien, puede forzar un redibujado para eliminar los cambios de estilo por lotes. Esto puede hacerse, por ejemplo, accediendo offsetHeight la propiedad del elemento:

$('img').show().each(function() { 
    this.offsetHeight; 
}).prop('src', 'image src'); 

Demostración: http://jsfiddle.net/F8Q44/266/

+0

Mejor tarde que nunca, ¡gracias! Entiendo cómo los navegadores completan los cambios de estilo, pero nunca pensé que se aplicaría en este caso de uso. Voy a experimentar un poco ahora. +1 para la información útil –

+0

He editado su respuesta para agregar la alternativa que usaría en un escenario real para poder aceptar su respuesta en lugar de enviar mi propia respuesta. Gracias. –

+0

¿Cómo puedo usar esto para restablecer un gif que está configurado como una imagen de fondo CSS y no como un SRC? Ejemplo: http://bit.ly/1XKm8JC - La imagen funciona bien en la primera reproducción, pero después de que termina la animación y vuelve al inicio, el gif de Seasons Greetings no comienza de nuevo. Estoy usando Edge Animate – KevinOrin

24

La forma más confiable de "reset" un GIF es añadiendo una cadena de consulta aleatoria. Sin embargo, esto significa que el GIF se volverá a descargar cada vez, así que asegúrese de que sea un archivo pequeño.

// reset a gif: 
img.src = img.src.replace(/\?.*$/,"")+"?x="+Math.random(); 
+2

+1, ya que realmente "soluciona" el problema en Chrome, a pesar de que solicitar una nueva descarga de imagen justo antes de mostrarla va en contra de mi concepto inicial de tenerlo ya en caché en la página. Mantendré la pregunta abierta un poco más para verificar si no hay otras soluciones posibles, ya que por ahora mantendría mi comportamiento falso de 'display: none'. –

+0

¿A dónde va este código? Me encantaría ver una versión funcional con jsFiddle – egr103

+1

Gracias por la gran solución de Niet. Esta es mi versión para 'background-image' (sin embargo, requiere jQuery):' img.css ('background-image', img.css ('background-image'). replace (".gif", ".gif" + "? x =" + Math.random())); ' – Stan

4

Este solution precargas del GIF y lo saca del dom y luego de vuelta en el src (evitando así otra descarga)

Acabo de probar que el uso de jQuery para quitar el atributo y trabaja muy bien.

Ejemplo:

<html> 
<head> 

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script> 

<script> 

$(function() { 

    $('.reset').click(resetGif); 

    function resetGif() 
    { 
     $('.img1').removeAttr('src', ''); 
    } 
}); 

</script> 

</head> 

<body> 
    <img class="img1" src="1.gif" /> 
    <a href="#" class="reset">reset gif</a> 
</body> 
</html> 
1

aquí está mi truco para imágenes de fondo:

$(document).on('mouseenter', '.logo', function() { 
    window.logo = (window.logocount || 0) + 1; 
    var img = new Image(); 
    var url = "/img/mylogimagename.gif?v=" + window.logocount; 
var that = this; 
    $(img).load(function(){ 

    $(that).css('background-image','url(' + url + ')'); 
    }); 
    img.src = url; 
}); 
+0

Hola, puede proporcionar algunos detalles sobre qué variables se deben cambiar para usar esto. Sé que var url sí, pero ¿pero qué más? – KevinOrin

2

Esto parecía funcionar para mí en Chrome, se ejecuta cada vez justo antes de desvanecerse en la imagen y borra luego vuelve a llenar el src y mi animación comienza desde el principio siempre.

var imgsrc = $('#my_image').attr('src'); 
$('#my_image').attr('src', ''); 
$('#my_image').attr('src', imgsrc); 
+0

¡La mejor solución! –

+0

Simple y efectivo: muchas gracias – alib0ng0

0

Me encontré con este hilo después de buscar muchos otros. La publicación de David Bell me llevó a la solución que necesitaba.

Pensé en publicar mi experiencia en el caso de que pudiera ser útil para cualquiera que intentara lograr lo que yo buscaba. Esto es para una aplicación web HTML5/JavaScript/jQuery que será una aplicación de iPhone a través de PhoneGap. Prueba en Chrome.

El objetivo:

  1. Cuando grifos usuario hace clic en el botón A /, aparece un gif animado y obras de teatro.
  2. Cuando el usuario toca/hace clic en el botón B, el archivo .gif desaparece.
  3. Cuando el usuario vuelva a hacer clic/haga clic en el botón A, después de tocar/hacer clic en el botón B, el gif animado debe reaparecer y reproducirse desde el principio.

El problema:

  • para el grifo/clic del botón A, que fue anexando el gif a un div existente. Jugaría bien.
  • Luego, al tocar/hacer clic en el botón B, estaba ocultando el contenedor div y luego estableciendo el img src del gif en una cadena vacía (''). De nuevo, no hay problema (es decir, el problema aún no era evidente)
  • Luego, al tocar/hacer clic en el botón A, después de presionar/hacer clic en el botón B, estaba volviendo a agregar la ruta al gif como el src.

    - Esto no funcionó. El gif se mostraría en los siguientes clics/pulsaciones del botón A ... sin embargo, cuanto más tocaba/hacía clic en el botón A, más veces el gif se cargaba y comenzaba de nuevo. Es decir, si iba y venía, tocando/haciendo clic en el botón A y luego el botón B 3 veces, el gif aparecía y luego comenzaba/detenía/comenzaba 3 veces ... y toda mi aplicación comenzó a sonar. Supongo que el archivo .gif se estaba cargando varias veces, a pesar de que había configurado el src en una cadena vacía cuando se hizo clic/clic en el botón B.

La solución:

Después de mirar el post de David Bell, llegué a mi respuesta.

  1. Definí una variable global (llamémosla myVar) que contenía el contenedor div y la imagen (con la ruta de origen) dentro.
  2. En la función de tocar/hacer clic del botón A, agregué ese contenedor div a un div principal existente en el dom.
  3. En esa función, creé una nueva variable que contiene la ruta src del gif.

Al igual que David sugirió, me hicieron esto (además de un append):

$('#mainParent').append(myVar); 
var imgsrc = $('#my_image').attr('src'); 
$('#my_image').attr('src', ''); 
$('#my_image').attr('src', imgsrc); 

entonces, en la función de botón B, me puse el src a una cadena vacía y luego se retira el div que contiene el gif:

$('#my_image').attr('src', ''); 
$('#mainParent').find('#my_image').remove(); 

Ahora, me puede tocar/haga clic en el botón A continuación, el botón B, entonces el botón A, etc., durante todo el día. El archivo .gif se carga y se reproduce al tocar/hacer clic en el botón A, luego se oculta al presionar/hacer clic en el botón B, luego se carga y reproduce desde el principio en los toques subsiguientes del botón A todas las veces, sin problemas.

2

Solo porque todavía necesito esto de vez en cuando me di cuenta de que la función JS pura que uso podría ser útil para otra persona. Esta es una forma pura de JS de reiniciar un gif animado, sin volver a cargarlo. Puede llamar esto desde un evento de carga de enlace y/o documento.

<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> 

En algunos exploradores solo necesita restablecer el archivo img.src en sí y funciona perfectamente. En IE, debes borrarlo antes de restablecerlo. Este resetGif() selecciona el nombre de la imagen de la identificación de la imagen. Esto es útil en caso de que alguna vez cambie el enlace de la imagen real para una identificación dada porque no tiene que recordar cambiar las llamadas a resetGiF().

--Nico

+0

Esta función funciona perfectamente. Lo único que tuve que cambiar para que funcione igualmente en chrome: 'img.src =" # ";' El reinicio si el primer src está completamente vacío. – vinni

0

He resuelto una solución completa para este problema. Se puede encontrar aquí: https://stackoverflow.com/a/31093916/1520422

Mi solución reinicia la animación SIN volver a cargar los datos de imagen de la red.

También refuerza la imagen para volver a pintar y corregir algunos artefactos de pintura que se produjeron (en cromo).

1

Tengo un botón con una imagen animada sin bucle. Simplemente recargo la imagen con algo de jquery y parece que me funciona.

var asdf = $(".settings-button img").attr("src"); 
$(".settings-button img").attr("src", "").attr("src", asdf); 
0

Tuve problemas con todas las soluciones anteriores. Lo que finalmente trabajado era la sustitución de la src temporalmente con un gif transparente de 1 píxel:

var transparent1PxGif = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; 
var reloadGif = function(img) { 
    var src = img.src; 
    img.src = transparent1PxGif; 
    img.offsetHeight; // triggers browser redraw 
    img.src = src; 
}; 
0

Ya han pasado varios años y he decidido volver a este, ya que tenemos una serie de nuevas opciones a nuestra disposición.

El problema con my previous answer es que obliga a volver a descargar el GIF cada vez que desea reiniciarlo. Si bien eso está bien para archivos pequeños, aún así es una sobrecarga que es mejor evitar si es posible.

Teniendo esto en cuenta, tengo una nueva solución que usa AJAX para descargar el GIF una vez y luego la convierte en una URL de datos (a través de un FileReader) y la utiliza como fuente con una cadena de consulta aleatoria adjunta .

De esta manera, el navegador solo descarga la imagen una vez, e incluso puede almacenarla en caché correctamente, y el "reinicio" se obtiene de ese recurso descargado previamente.

La única pega, por supuesto, es que tienes que asegurarte de que esté correctamente cargada antes de poder usarla.

Demostración: http://adamhaskell.net/misc/numbers/numbers.html

código relevante:

var url = "something.gif"; // fallback until the FileReader is done 
function setup() { 
    var xhr = new XMLHttpRequest(); 
    xhr.open("GET",url,true); 
    xhr.responseType = "blob"; 
    xhr.onreadystatechange = function() { 
     if(this.readyState == 4) { 
      var fr = new FileReader(); 
      fr.onload = function() { 
       url = this.result; // overwrite URL with the data one 
      }; 
      fr.readAsDataURL(this.response); 
     } 
    }; 
    xhr.send(); 
} 
function getGIF() { 
    return url+"?x="+Math.random(); 
} 
Cuestiones relacionadas