2009-08-26 4 views
62

Я попытался вставить и выключить DIV с помощью функции переключения jQuery, но результат всегда неустойчив в начале и/или конце анимации. Вот код JS, который я использую:jQuery slide is jumpy

$(document).ready(function(){ 
    $('#link1').click(
     function() { 
      $('#note_1').parent().slideToggle(5000); 
     } 
); 

И HTML:

<div class="notice"> 
    <p>Here's some text. And more text. <span id="link1">Test1</span></p> 
    <div class="wrapper"> 
     <div id="note_1"> 
      <p>Some content</p> 
      <p>More blalba</p> 
     </div> 
    </div> 
</div> 

Вы также можете увидеть полный пример здесь: jQuery Slide test

Я обычно использую Mootools, и я могу это сделать слайд без каких-либо проблем с ним. Но я начинаю новый проект в Django, и большинство приложений в Django используют jQuery. Поэтому для этого и после прочтения этого jQuery vs Mootools я решил, что это будет хороший повод начать использовать jQuery. Поэтому моя первая необходимость заключалась в том, чтобы спустить этот DIV. И это не сработало.

Я сделал больше поиска, и я обнаружил, что это старая ошибка в jQuery с полем и отступом, примененным к DIV. Решение состоит в том, чтобы обернуть DIV в другой DIV. В моем случае это не зафиксировало.

Поиск в дальнейшем Я нашел этот пост Slidedown animation jumprevisited. Он фиксирует скачок с одного конца, но не на другом (Test2 в jQuery Slide test).

На переполнение стека Я нашел это jQuery IE jerky slide animation. В комментариях я увидел, что проблема связана с тегом P внутри DIV. Если я заменяю теги P тегами DIV, которые исправляют проблему, но это не правильное решение.

И наконец, я нашел это Weird jQuery behavior slide. Читая это, я понял, что проблема, разрешенная путем переключения с P-тега на DIV, была с полями P (не присутствующими в DIV) и сбрасыванием полей между элементами. Поэтому, если я переключу поля на paddings, это устранит проблему. Но я теряю рушится поведение полей, рушится, что я хочу.

Честно говоря, я могу сказать, что мой первый опыт работы с jQuery на самом деле не очень хорош. Если я хочу использовать один из самых простых эффектов в jQuery, я должен не использовать правильную функцию (slideToggle), а вместо этого использовать какой-то ручной код И обернуть DIV в другой DIV и переключить поля в paddings, испортить мой макет.

Я пропустил более простое решение?

Как подсказывает krdluzni, я попытался написать как пользовательский скрипт с помощью метода animate. Вот мой код:

var $div = $('#note_2').parent(); 
var height = $div.height(); 

$('#link2').click(
    function() { 
     if ($div.height() > 0) { 
      $div.animate({ height: 0 }, { duration: 5000 }).css('overflow', 'hidden'); 
     } else { 
      $div.animate({ height : height }, { duration: 5000 }); 
     } 

     return false; 
}); 

Но это не работает, либо потому, что JQuery всегда установить переполнение виден в конце анимации. Таким образом, DIV перезаписывается в конце анимации, но накладывается на остальную часть контента.

Я пробовал также с UI.Slide (и масштаба и размера). Он работает, но контент ниже DIV не перемещается с анимацией. Он только прыгает в конце/начале анимации, чтобы заполнить пробел. Я не хочу этого.

UPDATE:

Одна часть раствора, чтобы установить высоту контейнера DIV динамически перед чем. Это решает один прыжок. Но не одна причина, сворачивая маржу.Вот код:

var parent_div = $("#note_1").parent(); 
parent_div.css("height", parent_div.height()+"px"); 
parent_div.hide(); 

ВТОРАЯ UPDATE:

Вы можете увидеть ошибку на собственном сайте JQuery на этой странице (пример B): Tutorials:Live Examples of jQuery

ТРЕТИЙ UPDATE:

Пробовал с jQuery 1.4, не более шансов :-(

+5

Прямо сейчас мне трудно поверить в лозунг «писать меньше, делать больше» jQuery. – Etienne

+0

Итак, это определенно не проблема с эквивалентными функциями mootools? – aaaidan

+0

Вы правы, что jQuery устанавливает отображение: none в конце анимации hide. Mootools этого не делает. – aaaidan

ответ

14

Попробуйте удалить все поля CSS из всех элементов. Обычно отрывистая анимация исходит из полей, которые не учитываются рамкой анимации.

+0

Как я его пишу, это исправляет проблему, если я удаляю поля из тега P и заменяю их на paddings. Но это не подходящее решение для меня, потому что это беспорядок мой макет, потому что я теряю рушится поведение полей. – Etienne

+0

Он уже определил, что его вызывает, но он заявил, что хочет, чтобы поля были полями. Удаление их против его спецификации. – krdluzni

+0

Etienne, вам нужно сначала удалить поля вокруг элемента, анимированного с помощью команды style(), а затем анимировать его. Вы по-прежнему будете сталкиваться с трудностями в верхнем и нижнем элементах и ​​должны обращаться с этими крайними случаями. –

2

Вы можете написать пользовательскую анимацию, используя метод animate. Это даст вам полный контроль над всеми деталями.

+0

Это стоит попробовать. Я никогда не использую встроенные события, если это не тривиальное шоу/скрытие. – Mike

+0

Это то, что я сделал, реализовав решение, показанное в «Сдвинутая анимация jumprevisited». Может быть, мне придется приспособить его, чтобы справиться с развалом полей. Я попробую это. JQuery должен был быть простым, и первая простая вещь, которую я хочу сделать, начинает быть действительно сложной. Наконец, я, вероятно, должен переопределить решение Mootools для слайда (без отображения: нет, поэтому DIV останется на месте с его полями) в jQuery. – Etienne

+0

Я пробовал по-разному с помощью метода анимации, и проблема всегда одна и та же. Если я использую hide/show, этот набор отображает значение none/block.Но с дисплеем: нет, я потерял поля DIV. Если я использую только анимацию с высотой 0. В конце анимации jQuery устанавливает переполнение на видимое, накладывая содержимое DIV, который предположительно должен быть скрыт. Любой способ, которым я пытаюсь, всегда есть дорожный блок :( – Etienne

0

Вы можете попробовать добавить doctype, если у вас его нет, он работал на меня в IE8 после того, как я нашел предложение здесь на SO: jQuery slideToggle jumps around. Он предлагает строгий DTD, но я просто использовал doctype, который использует google.com: <!doctype html>, и он исправил мою проблему.

+0

Спасибо за ответ. У меня уже есть DOCTYPE (XHTML-Transitional, а не строгий). см. ошибку на собственном сайте JQuery на странице с DOCTYPE XHTML-строкой здесь (пример B): http://docs.jquery.com/Tutorials:Live_Examples_of_jQuery – Etienne

+0

Пробовал IE8 и Chrome3. и понимаю, что вы имеете в виду. Похоже на проблему с jQuery. – Andrew

1

Вам просто нужно изменить эффекты вверх, вниз в effects.js, чтобы они учитывали поля или прокладки, которые могут существовать, а затем корректировать то, что они воспринимают, как общий размер элемента для размещения этих значений. . что-то в этом направлении ....

Effect.BlindDown = function(element) { 
    element = $(element); 
    var elementDimensions = element.getDimensions(); 

//below* 
    var paddingtop = parseInt(element.getStyle('padding-top')); 
    var paddingbottom = parseInt(element.getStyle('padding-bottom')); 
    var totalPadding = paddingtop + paddingbottom; 

    if(totalPadding > 0) 
    { 
    elementDimensions.height = (elementDimensions.height - totalPadding); 
    } 
//above* 

    return new Effect.Scale(element, 100, Object.extend({ 
    scaleContent: false, 
    scaleX: false, 
    scaleFrom: 0, 
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 
    restoreAfterFinish: true, 
    afterSetup: function(effect) { 
     effect.element.makeClipping().setStyle({height: '0px'}).show(); 
    }, 
    afterFinishInternal: function(effect) { 
     effect.element.undoClipping(); 
    } 
    }, arguments[1] || { })); 
}; 
+2

Спасибо за ваш ответ. Я попробую это, когда у меня появятся больше времени. что я не согласен со словом * просто * в «Вам просто нужно ...». Код, который вы предложили, далека от тривиальной функции (слайда), которая должна работать. Для меня это решение исправляет дефект в jQuery слайд funtion. Я, возможно, добавлю ошибку в свой трекер. – Etienne

33

Решение состоит в том, что раздвижной div должен иметь ширину, заданную в пикселях. Не используйте «auto» и «%». И у вас будет отличный результат! Проблема заключается в встроенных элементах, которые находятся в скользящем div.

но если они имеют ширину в px, высота будет одинаковой. Попробуй.

+2

Я попытался установить ширину в px раздвижного DIV без каких-либо успехов. Я также попытался установить ширину в px для каждого элемента раздвижного DIV, и это тоже ничего не меняет. У меня всегда есть странное поведение. Я уверен, что проблема заключается в разваливании полей. Я попробую jQuery 1.4 и посмотрю, сохранится ли проблема ... – Etienne

+0

Пробовал с jQuery 1.4, больше шансов :-( – Etienne

+1

На jQuery 1.6.2 это проблема по-прежнему остается проблемой. К счастью, это исправление по-прежнему работает! –

2

Я заметил, что у вас есть <br /> после вашего контейнера <div> анимация также будет нервной. Удаление этой проблемы устраняло мою проблему.

+0

Спасибо, но в моем примере у меня нет
. :( – Etienne

+0

Это помогло моей анимации тонну, ура! :) –

+0

уверенность в удовольствии – kingr

0

Я столкнулся с той же ошибкой, что и в течение нескольких дней, чтобы найти решение. проблема в том, когда элемент скрыт. jquery получает неправильную высоту. верхнее исправление, вы должны получить высоту перед тем, как скрыться, и использовать пользовательскую анимацию на этой высоте. его непростой путь here for a better explanation

+0

К сожалению, в моем случае это не сработает. 'Test 2' в моем' jQuery Slide test'. – Etienne

0

У меня была такая же проблема с «яростью» с divs внутри моего тега nav - моя цель - показать неупорядоченный список при наведении div (если таковой существует). Мои списки динамически создаются, поэтому они не имеют фиксированного значения.

Heres исправление:

$("nav div").hover(
    function() { // i.e. onmouseover function 

    /****simple lines to fix a % based height to a px based height****/ 
    var h = jQuery(this).find("ul").height(); //find the height 
    jQuery(this).find("ul").css("height", h); 
         //set the css height value to this fixed value 
    /*****************************************************************/ 

    jQuery(this).find("ul").slideDown("500"); 
    }, 
    function(){ // i.e. onmouseout function 
    jQuery(this).find("ul").slideUp("500"); 
    }); 
}); 
+0

У того же решения есть «Slidedown animation jumprevisited». Не работает в моем случае. – Etienne

41

Я нашел то, что работает последовательно устанавливает невидимую 1px границу:

border: 1px solid transparent;

Нет необходимости, чтобы установить ширину или высоту или что-нибудь еще и анимацию не прыгает. Ура!

+2

Это решение работает (вы также можете установить дополнение к 1px для того же результата) в том смысле, что анимация не прыгает. Но меня это не устраивает, потому что, устанавливая границу или заполнение, то, что она на самом деле делает, останавливает свертывание полей между дочерними и родительскими. И это рушится - это то, что я хочу сохранить (см. Мой вопрос). – Etienne

+0

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

+1

Даже если я этого не понимаю - это действительно простой способ исправить рывок :) Я использую Bootstrap 3 – legas

1

Попробуйте установить свойство 'position' контейнера (в данном случае .notice div) на 'relative'.

Работал для меня. slideToggle height is "jumping"

+0

Я просто попробовал это, и он не работает ни в моем случае. Я попытался установить 'position' в' relative' в контейнер, на скользящий div, на все и т. Д., И анимация все еще прыгает. – Etienne

0

В моем случае я решил добавить элемент style="white-space:nowrap;" к элементу, чтобы предотвратить просчеты функции jQuery; нет необходимости устанавливать фиксированную ширину, если вам не нужно обертывать.

0

Убедитесь, что у вас нет правил перехода CSS, установленных глобально или на вашем контейнере или в любых входящих элементах. Это также вызовет дерзость.

19

Сегодня я столкнулся с этой проблемой. Однако я заметил, что отключение всех CSS исправило проблему. Кроме того, я знал, что это сработало хорошо, поэтому, должно быть, это были недавние изменения, вызвавшие эту проблему.

Оказалось, что я использовал переходы в CSS для облегчения вхождения и выключения из-за зависания.

Как только эти переходы были удалены из элементов, которые я добавлял, все было в порядке.

Так что если у вас есть такая же проблема, просто добавьте эти строки элементов добавляемых:

-webkit-transition: none; 
-moz-transition: none; 
-o-transition: none; 
-ms-transition: none; 
transition: none; 

(я, возможно, злоупотребляют переходы немного, не просто добавляя их к элементам, которые я хочу имеют переходы, но используют их для всего веб-сайта.)

+1

Просто столкнулся с этой проблемой, и я забыл, что у меня был переход на CSS, и это вызывает проблемы для jQuery. – Britton

+1

Работал. Спасибо :) – yuvalsab

+0

Лучший ответ. Решила мою проблему. Большое спасибо –

0

Сегодня в этом выпуске этот вопрос увидел этот вопрос и начал возиться с тем, что я увидел здесь. Я решил нашу нерешительную проблему, удалив позицию: относительно CSS содержащего div. После этого больше нет странности. Мои 2 цента.

3

Я нахожу, что animate() - самый надежный способ анимировать что-либо в jQuery (по крайней мере, в кросс-браузере).

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

http://jsfiddle.net/BmWjy/13/

$('a').click(function(event) { 
     event.preventDefault(); 
     xToggleHeight($(this).next()); 
}); 

//For each collapsible element. 
$('.collapsible').each(function() { 
     //Wrap a div around and set to hidden. 
     $(this).wrap('<div style="height:0;overflow:hidden;visibility:hidden;"/>'); 
}); 

function xToggleHeight(el){ 
     //Get the height of the content including any margins. 
     var contentHeight = el.children('.collapsible').outerHeight(true); 
     //If the element is currently expanded. 
     if(el.hasClass("expanded")){ 
       //Collapse 
       el.removeClass("expanded") 
         .stop().animate({height:0},5000, 
         function(){ 
           //on collapse complete 
           //Set to hidden so content is invisible. 
           $(this).css({'overflow':'hidden', 'visibility':'hidden'}); 
         } 
       ); 
     }else{ 
       //Expand 
       el.addClass("expanded").css({'overflow':'', 'visibility':'visible'}) 
         .stop().animate({height: contentHeight},5000, 
         function(){ 
           //on expanded complete 
           //Set height to auto incase browser/content is resized afterwards. 
           $(this).css('height',''); 
         } 
       ); 
     } 
} 
2

Есть много предложений здесь и много вперед и назад, как что работает. Для меня проблема с поведением заключалась в том, что анимация расширения контейнера будет расширяться, а затем возвращаться к правильной высоте расширения (все это делается как часть одной анимации). В качестве примера анимация будет сначала расширяться до высоты 500 пикселей, а затем втягиваться в 450 пикселей. Не было никаких проблем с крахом.

Решение, которое работало, состояло в том, чтобы добавить к расширяющемуся/сворачивающемуся div, CSS: white-space: nowrap;

Это отлично работает - плавное расширение до правильной высоты.

+0

Не работал для меня. – supertrue

2

css padding и jquery slideToggle не работает хорошо вместе. Попробуйте выставить прокладку.

0

Я использовал slideDown() как этот

$('#content').hide().delay(500).slideDown(500); 

Для меня это был главный контейнер #content элемент. Я спрятал его, а затем позвонил slideDown(). Я удалил свойство padding в CSS, и после этого все сработало. Обычно это margin, padding или% width, поэтому самый простой метод - это комментирование каждого свойства и тестирование их 1 на 1 для получения ваших результатов.

2

Очевидно, есть много разных решений этой проблемы - и в зависимости от вашего макета разные решения имеют разные результаты.

Здесь было то, что я (урезанная)

<div> 
    <p>Text</p> 
</div> 
<div class="hidden"> 
    <p></p> 
</div> 

Когда я хотел бы использовать JQuery, чтобы показать <div class="hidden">, запас на <p> элемент разрушится с краю <p> элемента над ним.

Я думал, что это странно, так как они были в разных <divs>.

Моим решением было устранить край в нижней части <p>. Имея маржу на одной стороне, предотвращает срыв края с нижней части первого <p> с верхней частью второй <p>.

Это обходное решение решило мою проблему, возможно, применимо к другим, но может не работать для всех.

+0

Ничего себе ... поля рушатся друг на друга. Благодаря! Это своего рода смешно ... – SeanKendle

0

У меня была такая же проблема, но ни один из предлагаемых решений не работал для меня, поэтому я предлагаю решение, которое полностью исключает возможность использования slideToggle().

Спарка Примечание: Загрузите страницу в обычном режиме, собирать высоту каждого элемента, который вы хотите переключить, хранить эту высоту в специальном атрибуте данных, а затем рухнуть каждый элемент. Тогда это так же просто, как изменение max-height между значением в атрибуте data-height элемента (расширенным) и нулевым (свернутым). Если вы хотите добавить дополнительные элементы и поля и т. Д. К элементам, я рекомендую хранить их в отдельном классе CSS для добавления и удаления с помощью свойства max-height.

Поместите jQuery прямо после элементов, которые вы хотите переключить, и разрешите им выполнять во время загрузки страницы (чтобы вам не приходилось следить за их загрузкой и затем сбрасывать).

HTML

<ul id="foo"> 
    <li> 
     <h2>Click Me 1</h2> 
     <div class="bar">Content To Toggle Here 1</div> 
    </li> 
    <li> 
     <h2>Click Me 2</h2> 
     <div class="bar">Content To Toggle Here 2</div> 
    </li> 
</ul> 

CSS

#foo>li>div.bar {transition: all 0.5s; 
    overflow: hidden;} 

JQuery

$('#foo h2').each(function(){ 
    var bar = $(this).siblings('.bar'); 
    bar.attr('data-height', bar.height()); //figure out the height first 
    bar.css('max-height', '0px'); //then close vertically 
}); 
$('#foo h2').click(function(){ 
    var bar = $(this).siblings('.bar'); 
    if (bar .css('max-height') == '0px'){ //if closed (then open) 
     bar.css('max-height', bar.data('height') + 'px'); 
    } else { //must be open (so close) 
     bar.css('max-height', '0px'); 
    } 
}); 

Здесь является рабочим JSFiddle: http://jsfiddle.net/baacke/9WtvU/

1

Проблема в том, что вы выполняете действие над родителем, и это удаляет CSS, связанный с этим элементом.

Вам нужно запустить слайд на вашем Note1, а не родитель записки 1.

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

+0

Скользящий 'note1' вместо родителя не исправляет проблему в моем случае. – Etienne

0

У меня была такая же проблема.Я установил его, добавив это:

.delay(100)

Guess придав ему больше времени, чтобы думать, что помогает вместе?

0

Я только что узнал, что эта проблема также может возникнуть, если в расширяющемся/свертывающемся элементе имеются элементы с плавающей точкой. В этом случае clearfix (clear: both;) в конце (все еще внутри) анимированный элемент может избавиться от него.

4

Дрессировка происходит, когда родительский div «.wrapper»в вашем случае имеет набивку.

Прокладка идет на дочерний div, а не на родителя. jQuery - это анимация высоты, а не заполнение.

Пример:

<div class="notice"> 
    <p>Here's some text. And more text. <span id="link1">Test1</span></p> 
    <div class="wrapper" style="padding: 0"> 
     <div id="note_1" style="padding: 20px"> 
      <p>Some content</p> 
      <p>More blalba</p> 
     </div> 
    </div> 
    </div> 

Надеется, что это помогает.

+0

Это сработало для меня ... спасибо !!! – chris

+0

Рад, что это помогло! –

+1

Не могу поверить, что они не приняли это в качестве ответа. –

0

Добавление моего решения: оказалось, что моя проблема была flexbox (только в хром). У меня было align-items: baseline;, установленное на родительском элементе. Установите align-self: center; в мой элемент childtoggling full-width и он очистит его. Большое использование двух часов.

0

Я решил, установив:

box-sizing: content-box; 
1

Для меня удаления мин-высота от моего контейнера решить эту проблему.

0

Для меня решение было то, что я имел CSS определение стиля, как следующее:

* { 
    transition: all .3s; 
} 

Удаление это решение!