jQuery Animation — плавный переход размера

Так что это может быть очень просто, но я пока не смог найти ни одного примера, на котором можно было бы учиться, поэтому, пожалуйста, потерпите меня. ;)

Вот в основном то, что я хочу сделать:

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

.... 

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

Я хочу плавно анимировать между размерами div с большим количеством контента и размерами div с очень небольшим количеством контента, когда вводится новый контент.

Мысли?


person neezer    schedule 28.10.2008    source источник


Ответы (8)


Попробуйте этот плагин 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);

Комментатор RonLugge отмечает, что это может вызвать проблемы, если вы вызовете его дважды для одного и того же элемента (элементов), когда первая анимация не закончилась до начала второй. Это связано с тем, что вторая анимация примет текущие (средние) размеры в качестве желаемых «конечных» значений и перейдет к их фиксации в качестве окончательных значений (фактически останавливая анимацию на своих дорожках, а не приближаясь к «естественному» размеру). )...

Самый простой способ решить эту проблему — вызвать stop() перед вызовом showHtml() и передать true для второго (< em>jumpToEnd):

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

Это приведет к немедленному завершению первой анимации (если она все еще выполняется) перед началом новой.

person Shog9    schedule 28.10.2008
comment
В чем смысл переменной Finish? И чем он отличается от кур? - person ecoffey; 03.11.2009
comment
@ecoffey: finish содержит начальное и конечное значения для стилей width и height. Он всегда будет отличаться от cur, который представляет стили, необходимые для фиксации элемента на его начальной ширине и высоте; если бы они когда-либо были одинаковыми, то размеры элемента не менялись бы вместе с его содержимым, и эта анимация была бы бессмысленной! - person Shog9; 03.11.2009
comment
вы должны вернуть this.each - person Matt; 03.11.2009
comment
@ Shog9: а, хорошо, спасибо; Думаю, у меня было другое представление о том, что происходит. Может быть, мне следует просто нажать Ctrl+C / Ctrl+V и посмотреть, как он работает, прежде чем продолжать его критиковать :-P - person ecoffey; 03.11.2009
comment
Этот код подвержен ошибкам, если два вызова идут слишком близко друг к другу — например, если запрос AJAX для нового контента возвращается достаточно быстро, чтобы произойти, пока анимация «AJAX QUERY RUNNING» все еще выполняется. - person RonLugge; 24.08.2011
comment
@Ron: если вы запускаете две анимации подряд, они могут мешать ... Я не верю, что продемонстрировал это, но если вы хотите использовать анимацию загрузки, тогда промежуточный вызов stop() в порядке. - person Shog9; 24.08.2011
comment
Спасибо за быстрый ответ! Куда бы вы поместили промежуточный вызов stop()? Я попытался поместить его непосредственно перед вызовом второго .showHtml(), но это не сработало. - person RonLugge; 24.08.2011
comment
@Ron: Вам нужно заставить текущую анимацию фактически завершиться (а не просто остановиться), передав true для второго параметра в stop(). Я обновил ответ с подробностями. - person Shog9; 24.08.2011
comment
Спасибо! Я не хотел открывать свой собственный вопрос, когда, честно говоря, этот вопрос был на 99,9999% нужным мне решением. Как-то избыточно. - person RonLugge; 24.08.2011

Вы можете использовать метод анимации.

$("div").animate({width:"200px"},400);
person Josh Bush    schedule 28.10.2008
comment
Идеально! Я только что добавил $("div").stop(true,true); прямо перед вызовом вашего оператора, чтобы убедиться, что анимация не поставлена ​​в очередь. - person Flo; 08.09.2016

может что-то вроде этого?

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

Близко к тому, что, я думаю, вы хотели, также попробуйте slideIn/slideOut или посмотрите на плагин UI/Effects.

person lucas    schedule 28.10.2008
comment
Не совсем то, к чему я стремился. При этом Div сжимается до нуля, прежде чем снова расширяться. Я хочу устранить эту среднюю усадку, чтобы она переходила непосредственно в новые измерения без обнуления промежуточных значений. Имеет ли это смысл? Похоже, ни одна из демонстраций для пользовательского интерфейса/эффектов не делает этого. - person neezer; 29.10.2008

Вот как я это исправил, надеюсь, это будет полезно! Анимация плавная на 100% :)

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

Там может быть более короткая версия моего кода, но я просто оставил ее такой.

person Daan    schedule 24.01.2009
comment
Мне никогда не приходила в голову идея иметь fadeIn внутри события успеха fadeOut, спасибо! - person Curt; 07.10.2010
comment
На самом деле это обратный звонок, а не событие успеха - person Jimmy; 10.12.2010

Это делает работу для меня. Вы также можете добавить ширину к временному 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();
  });
});
person A-P    schedule 12.05.2011

Здравствуйте, meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt.

Вы можете обернуть «контент div» «внешним div», для которого установлено значение абсолютной ширины. Вставьте новый контент с помощью метода «hide ()» или «animate ({width})», показанного в других ответах. Таким образом, страница не перекомпоновывается между ними, потому что div-оболочка имеет постоянную ширину.

person micahwittman    schedule 28.10.2008

Вы можете сгладить анимацию jQuery, используя dequeue. Проверяйте наличие класса (устанавливается при наведении и удаляется при обратном вызове анимации mouseOut) перед просмотром новой анимации. Когда новая анимация действительно запустится, удалите ее из очереди.

Вот небольшая демонстрация.

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

Демонстрация настроена как 5 столбцов полной высоты, щелчок по любому из столбцов со 2 по 5 анимирует ширину переключения остальных 3 и перемещает выбранный элемент в крайнее левое положение.

введите здесь описание изображения

введите здесь описание изображения

person davidcondrey    schedule 26.11.2014

Чтобы использовать решение плагина jquery (слишком низкая репутация, чтобы добавить это в качестве комментария), jQuery.html() удалит все обработчики событий в добавленном html. Изменение:

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

to

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

сохранит обработчики событий элементов "html"

person snotbubblelou    schedule 17.12.2014