2008-10-28 11 views
33

Así que esto podría ser realmente simple, pero no he podido encontrar ningún ejemplo para aprender aún, así que por favor tengan paciencia conmigo. ;)jQuery Animation - Smooth Size Transition

Aquí es básicamente lo que quiero hacer:

<div>Lots of content! Lots of content! Lots of content! ...</div> 

.... 

$("div").html("Itsy-bitsy bit of content!"); 

Quiero animar suavemente entre las dimensiones de la div con un montón de contenido a las dimensiones de la div con muy poco cuando el nuevo contenido está inyectado.

¿Pensamientos?

Respuesta

46

Prueba este plugin de jQuery:

// Animates the dimensional changes resulting from altering element contents 
// Usage examples: 
// $("#myElement").showHtml("new HTML contents"); 
// $("div").showHtml("new HTML contents", 400); 
// $(".className").showHtml("new HTML contents", 400, 
//     function() {/* on completion */}); 
(function($) 
{ 
    $.fn.showHtml = function(html, speed, callback) 
    { 
     return this.each(function() 
     { 
     // The element to be modified 
     var el = $(this); 

     // Preserve the original values of width and height - they'll need 
     // to be modified during the animation, but can be restored once 
     // the animation has completed. 
     var finish = {width: this.style.width, height: this.style.height}; 

     // The original width and height represented as pixel values. 
     // These will only be the same as `finish` if this element had its 
     // dimensions specified explicitly and in pixels. Of course, if that 
     // was done then this entire routine is pointless, as the dimensions 
     // won't change when the content is changed. 
     var cur = {width: el.width()+'px', height: el.height()+'px'}; 

     // Modify the element's contents. Element will resize. 
     el.html(html); 

     // Capture the final dimensions of the element 
     // (with initial style settings still in effect) 
     var next = {width: el.width()+'px', height: el.height()+'px'}; 

     el .css(cur) // restore initial dimensions 
      .animate(next, speed, function() // animate to final dimensions 
      { 
       el.css(finish); // restore initial style settings 
       if ($.isFunction(callback)) callback(); 
      }); 
     }); 
    }; 


})(jQuery); 

comentarista RonLugge señala que esto puede causar problemas si se llama dos veces en el mismo elemento (s), en donde la primera animación no ha terminado antes de que comience la segunda . Esto se debe a que la segunda animación tomará los tamaños actuales (mid-animation) como los valores deseados de "finalización" y procederá a corregirlos como los valores finales (deteniendo efectivamente la animación en lugar de animar hacia el tamaño "natural") ...

la forma más fácil de resolver este es llamar stop() antes de llamar showHtml(), y pasando true para la segunda) parámetro (jumpToEnd:

$(selector).showHtml("new HTML contents") 
      .stop(true, true) 
      .showHtml("even newer contents"); 

esto hará que la primera animación para completar inmediatamente (si todavía está funcionando), antes de comenzar uno nuevo.

+0

¿Cuál es el punto de la variable de finalización? ¿Y cómo es diferente de cur? – ecoffey

+0

@ecoffey: 'finish' contiene los valores iniciales y finales para los estilos' width' y 'height'. Siempre será diferente de 'cur', que representa los estilos necesarios para fijar el elemento en su ancho y alto iniciales; si fueran iguales, entonces las dimensiones del elemento no cambiarían con su contenido, ¡y esta animación sería inútil! – Shog9

+0

debería devolver este. – Matt

6

tal vez algo como esto?

$(".testLink").click(function(event) { 
    event.preventDefault(); 
    $(".testDiv").hide(400,function(event) { 
     $(this).html("Itsy-bitsy bit of content!").show(400); 
    }); 
}); 

Cerca de lo que creo que quería, también tratar slideIn/slideOut o buscar en la interfaz de usuario/plugin de efectos.

+0

No es exactamente lo que yo buscaba. Con esto, la Div se reduce a nada antes de expandirse nuevamente. Quiero eliminar esa contracción media, por lo que va directamente a las nuevas dimensiones sin que se produzca una separación cero entre ellas. ¿Tiene sentido? Ninguna de las demos para UI/Effects parece hacer esto tampoco. – neezer

41

Puede usar el animate method.

$("div").animate({width:"200px"},400); 
+1

¡Perfecto! Acabo de agregar '$ (" div "). Stop (verdadero, verdadero);' justo antes de llamar a su estado de cuenta para asegurarme de que las animaciones no estén en cola. – Flo

0

Hola meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt.

Puede envolver el 'contenido div' con un 'div externo' que se establece en un valor de ancho absoluto. Inyecte el nuevo contenido con un método "hide()" o "animar ({ancho})", que se muestra en las otras respuestas. De esta manera, la página no se redistribuye porque el div wrapper tiene un ancho estable.

6

Así es como lo arreglé, ¡espero que sea útil! La animación es 100% :) suave

HTML:

<div id="div-1"><div id="div-2">Some content here</div></div> 

Javascript:

// cache selectors for better performance 
var container = $('#div-1'), 
    wrapper = $('#div-2'); 

// temporarily fix the outer div's width 
container.css({width: wrapper.width()}); 
// fade opacity of inner div - use opacity because we cannot get the width or height of an element with display set to none 
wrapper.fadeTo('slow', 0, function(){ 
    // change the div content 
    container.html("<div id=\"2\" style=\"display: none;\">new content (with a new width)</div>"); 
    // give the outer div the same width as the inner div with a smooth animation 
    container.animate({width: wrapper.width()}, function(){ 
     // show the inner div 
     wrapper.fadeTo('slow', 1); 
    }); 
}); 

Puede haber una versión más corta de mi código, pero yo sólo lo mantuvo así.

+0

la idea de tener fadeIn dentro de fadeOut evento de éxito nunca se me ocurrió, ¡gracias! – Curt

+0

En realidad es una devolución de llamada y no un evento exitoso – Jimmy

1

Esto hace el trabajo por mí. También puede agregar un ancho al div. Temporal.

$('div#to-transition').wrap('<div id="tmp"></div>'); 
$('div#tmp').css({ height: $('div#to-transition').outerHeight() + 'px' }); 
$('div#to-transition').fadeOut('fast', function() { 
    $(this).html(new_html); 
    $('div#tmp').animate({ height: $(this).outerHeight() + 'px' }, 'fast'); 
    $(this).fadeIn('fast', function() { 
    $(this).unwrap(); 
    }); 
}); 
0

Puede suavizar la animación jQuery usando dequeue. Pruebe la presencia de clase (se establece al pasar el mouse y se quita en el mouse, sin devolución de llamada animada) antes de mirar una nueva animación. Cuando se inicia una nueva animación, dequeue.

Here's a quick demo.

var space = ($(window).width() - 100); 
$('.column').width(space/4); 

$(".column").click(function(){ 
    if (!$(this).hasClass('animated')) { 
     $('.column').not($(this).parent()).dequeue().stop().animate({width: 'toggle', opacity: '0.75'}, 1750,'linear', function() {}); 
    } 

    $(this).addClass('animated'); 
    $('.column').not($(this).parent()).dequeue().stop().animate({width: 'toggle', opacity: '0.75'}, 1750,'linear', function() { 
      $(this).removeClass('animated').dequeue(); 

     }); 
    $(this).dequeue().stop().animate({ 
     width:(space/4) 
    }, 1400,'linear',function(){ 
     $(this).html('AGAIN'); 
    }); 
}); 

La demostración se configura como 5 columnas de altura completa, hacer clic en cualquiera de las columnas 2 al 5 que animará la anchura de palanca de los otros 3 y mover el elemento se ha hecho clic en el extremo izquierdo.

enter image description here

enter image description here

0

Para el de lengüeta en la solución plugin de jQuery (demasiado bajo de la reputación de añadir esto como un comentario) jQuery.html() eliminará cualquier controlador de eventos en el html anexa. Cambiante:

// Modify the element's contents. Element will resize. 
el.html(html); 

a

// Modify the element's contents. Element will resize. 
el.append(html); 

retendrá los controladores de eventos de los elementos de "HTML"