2008-10-28 15 views
33

To może być naprawdę proste, ale nie znalazłem żadnych przykładów, aby się uczyć, więc proszę o zachowanie mnie. ;)Animacja jQuery - płynne przenoszenie rozmiaru

Tutaj w zasadzie to, co chcę zrobić:

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

.... 

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

Chcę płynnie animować między wymiarami div z dużą ilością treści do wymiarów div z bardzo mało kiedy nowa treść jest wstrzyknięty.

Myśli?

Odpowiedz

46

Spróbuj jQuery plugin:

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

Commenter RonLugge zwraca uwagę, że może to powodować problemy, jeśli nazywają go dwa razy na ten sam element (y), gdzie pierwsza animacja nie zostało zakończone przed drugą zaczyna . Dzieje się tak dlatego, że druga animacja przyjmuje bieżące (średnie animacje) rozmiary jako pożądane wartości "kończące" i przystępuje do ich naprawienia jako ostatecznych wartości (skutecznie zatrzymuje animację w swoich ścieżkach, zamiast animować w kierunku "naturalnego" rozmiaru) ...

Najprostszym sposobem rozwiązania tego jest wywołanie stop() przed wywołaniem showHtml() i przechodząc true dla drugiego (jumpToEnd) parametru:

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

to spowoduje pierwszą animację, aby zakończyć natychmiast (jeśli nadal działa), przed rozpoczęciem nowego.

+0

Jaki jest sens zmiennej zakończenia? Czym różni się od cur? – ecoffey

+0

@ecoffey: 'finish' zawiera wartości początkowe i końcowe dla stylów' width' i 'height'. Zawsze będzie różnił się od 'cur', który reprezentuje style potrzebne do zamocowania elementu na jego początkowej szerokości i wysokości; gdyby były takie same, wymiary elementu nie zmieniłyby się wraz z zawartością, a ta animacja byłaby bezcelowa! – Shog9

+0

powinieneś zwracać. To znaczy: – Matt

6

może coś takiego?

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

Blisko tego, o czym myślę, że chciałeś, również spróbuj slideIn/slideOut lub spójrz na wtyczkę UI/Effects.

+0

Niekoniecznie co ja jechałem za. W ten sposób DIV zmniejsza się do zera przed ponownym rozszerzeniem. Chcę wyeliminować ten pośredni skurcz, aby trafił bezpośrednio do nowych wymiarów bez zera między nimi. Czy to ma sens? Wygląda na to, że żadne z pokazów na UI/efekty nie działa. – neezer

41

Możesz użyć animate method.

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

Idealny! Właśnie dodałem '$ (" div "). Stop (true, true);' tuż przed wywołaniem twojego wyciągu, aby upewnić się, że animacje nie są w kolejce. – Flo

0

Witaj meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt.

Można zawinąć "div zawartości" za pomocą "zewnętrznego div", który jest ustawiony na bezwzględną wartość szerokości. Wstrzyknij nową zawartość za pomocą metody "hide()" lub "animate ({width})", pokazanej w innych odpowiedziach. W ten sposób strona nie zostanie ponownie zapisana, ponieważ opakowanie jednostkowe div ma stałą szerokość.

6

Oto jak to naprawiłem, mam nadzieję, że będzie to przydatne! Animacja jest 100% gładka :)

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

Nie może być krótsza wersja mojego kodu, ale po prostu trzymał go w takim stanie.

+0

pomysł, aby mieć fadeIn wewnątrz eventu fadeOut, nigdy nie przyszło mi do głowy, dzięki! – Curt

+0

To rzeczywiście oddzwonienie, a nie zdarzenie sukcesu – Jimmy

1

Wykonuje to za mnie. Możesz również dodać szerokość do temp div.

$('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

można wygładzić za pomocą animacji jQuery dequeue. Przetestuj obecność klasy (ustawiona na zawisie i usunięta przy pomocy mouseOut anime callback) przed uruchomieniem nowej animacji. Kiedy zaczyna się nowa animacja, usuń kolejkę.

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

Demo jest ustawiony jako 5 kolumn o pełnej wysokości, klikając każdy z kolumn 2 thru 5 będzie animować szerokość przełączania drugiej 3 i przesunąć element kliknąć, aby po lewej stronie.

enter image description here

enter image description here

0

piggy-back na rozwiązanie jQuery plugin (zbyt niskiej reputacji, aby dodać to jako komentarz) jQuery.html() usunie wszelkie obsługi zdarzeń na załączonym html. Zmiana:

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

do

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

zachowa obsługi zdarzeń z "html" elementów