web-dev-qa-db-fra.com

jQuery Animation - Transition de taille fluide

Donc, cela pourrait être très simple, mais je n'ai pas encore trouvé d'exemples à tirer, alors soyez indulgent avec moi. ;)

Voici essentiellement ce que je veux faire:

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

.... 

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

Je veux animer en douceur entre les dimensions de la div avec beaucoup de contenu aux dimensions de la div avec très peu lorsque le nouveau contenu est injecté.

Pensées?

33
neezer

Essayez ce plugin 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);

Le commentateur RonLugge souligne que cela peut causer des problèmes si vous l'appelez deux fois sur le même élément (s), où la première animation n'est pas terminée avant le début du second. Cela est dû au fait que la deuxième animation prendra les tailles actuelles (mi-animation) comme valeurs de "fin" souhaitées et procédera à les fixer comme valeurs finales (arrêtant effectivement l'animation sur ses pistes plutôt que d'animation vers la taille "naturelle") ) ...

La façon la plus simple de résoudre ce problème consiste à appeler stop() avant d'appeler showHtml() et de passer true pour le second ( paramètre jumpToEnd ):

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

Cela entraînera la première animation à se terminer immédiatement (si elle est toujours en cours d'exécution), avant de commencer une nouvelle.

47
Shog9

Vous pouvez utiliser la méthode animée .

$("div").animate({width:"200px"},400);
42
Josh Bush

peut-être quelque chose comme ça?

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

Proche de ce que je pense que vous vouliez, essayez également slideIn/slideOut ou regardez le plugin UI/Effects.

6
lucas

Voici comment j'ai corrigé cela, j'espère que ce sera utile! L'animation est 100% fluide :)

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);
    });
});

Il pourrait y avoir une version plus courte de mon code, mais je l'ai juste gardé comme ça.

6
Daan

Cela fait le travail pour moi. Vous pouvez également ajouter une largeur à la div temp.

$('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();
  });
});
1
A-P

Vous pouvez lisser l'animation jQuery en utilisant dequeue. Testez la présence de la classe (définie lors du survol et supprimée lors du rappel de l'animation mouseOut) avant de lancer une nouvelle animation. Lorsqu'une nouvelle animation démarre, retirez la file d'attente.

Voici une démo rapide.

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 démo est configurée en 5 colonnes pleine hauteur, cliquer sur l'une des colonnes 2 à 5 animera la largeur de basculement des 3 autres et déplacera l'élément cliqué à l'extrême gauche.

enter image description here

enter image description here

0
davidcondrey

Bonjour meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt.

Vous pouvez envelopper la "div de contenu" avec une "div externe" qui est définie sur une valeur de largeur absolue. Injectez le nouveau contenu avec une méthode "hide ()" ou "animate ({width})", comme indiqué dans les autres réponses. De cette façon, la page ne se redistribue pas entre les deux car le div wrapper détient une largeur constante.

0
micahwittman

Pour utiliser la solution du plug-in jquery (réputation trop faible pour l'ajouter en tant que commentaire) jQuery.html () supprimera tous les gestionnaires d'événements sur le html ajouté. En changeant:

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

à

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

conservera les gestionnaires d'événements des éléments "html"

0
snotbubblelou