jQuery幻灯片是跳跃的

时间:2009-08-26 15:12:36

标签: javascript jquery

我尝试使用jQuery的切换功能滑入和滑出DIV,但结果总是在动画的开始和/或结束处跳跃。这是我使用的js代码:

$(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中的大多数app都使用jQuery。因此,在阅读此jQuery vs Mootools后,我认为这将是开始使用jQuery的好机会。所以我的第一个需要是滑动这个DIV。而且它没有正常工作。

我做了更多搜索,我发现这是jQuery中的一个旧错误,边缘和填充应用于DIV。解决方案是将DIV包装在另一个DIV中。它没有解决我的问题。

进一步搜索我发现了这篇文章Slidedown animation jumprevisited。它修复了一端的跳转而不是另一端的跳转(<{3>}中的 Test2 )。

在Stack Overflow上我找到了这个jQuery Slide test。在评论中,我看到问题在于DIV中的P标签。如果我用解决问题的DIV标签替换P标签,但这不是一个合适的解决方案。

最后我发现了这个jQuery IE jerky slide animation。阅读它我理解通过从P标签切换到DIV解决的问题是P的边缘(DIV中不存在)和元素之间边距的崩溃。因此,如果我将边距切换为填充,则可以解决问题。但是我放松了边缘的崩溃行为,摧毁了我想要的东西。

老实说,我可以说我对jQuery的第一次体验并不是很好。如果我想使用jQuery中最简单的效果之一,我必须不使用正确的函数(slideToggle),而是使用一些手工制作的代码并将DIV包装在另一个DIV中并将边距切换到填充,弄乱我的布局。

我是否想念一个更简单的解决方案?

正如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(以及Scale和Size)。它可以工作,但DIV下面的内容不随动画移动。它只会在动画结束/开始时跳转以填补空白。我不希望这样。

更新

解决方案的一部分是在任何事情之前动态设置容器DIV的高度。这解决了一个跳跃。但不是因为利润率下降导致的原因之一。这是代码:

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

第二次更新:

您可以在此页面上看到jQuery自己网站上的错误(示例B): Weird jQuery behavior slide

第三次更新:

尝试使用jQuery 1.4,不再有机会: - (

28 个答案:

答案 0 :(得分:42)

我发现一致的是设置一个不可见的1px边框:

border: 1px solid transparent;

无需修复宽度或高度或其他任何内容,动画也不会跳转。万岁!

答案 1 :(得分:33)

解决方案是滑动div的宽度必须设置为像素。不要使用'auto'和'%'。而且你会有很好的结果!问题在于滑动div中的内联元素。

但如果它们的宽度为px,则高度相同。试试吧。

答案 2 :(得分:21)

我今天遇到了这个问题。我注意到,禁用所有CSS修复了问题。此外,我知道它之前工作正常,所以最近的变化一直是造成这个问题的原因。

事实证明我在CSS中使用过渡来缓和进出悬停

从元素中删除这些过渡后,我添加的一切都很好。

因此,如果您遇到同样的问题,只需将这些行添加到您要添加的元素中:

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

(我可能已经滥用了一些转换,不仅仅是将它们添加到我想要转换的元素中,而是将它们用于整个网站。)

答案 3 :(得分:14)

尝试从所有元素中删除所有CSS边距。通常,生涩动画来自动画框架未考虑的边距。

答案 4 :(得分:4)

当您的案例中的父div&#34; .wrapper&#34; 具有填充时,就会发生Jerking。

Padding继续使用子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>

希望这有帮助。

答案 5 :(得分: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','');
                        }
                );
        }
}

答案 6 :(得分:2)

您可以使用animate方法编写自定义动画。这将使您可以绝对控制所有细节。

答案 7 :(得分:2)

我从容器中移除最小高度解决了问题。

答案 8 :(得分:2)

这个问题显然有很多不同的解决方案 - 根据您的布局,不同的解决方案会有不同的结果。

这就是我所拥有的(剥离)

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

当我使用jQuery显示<div class="hidden">时,<p>元素上的边距会因其上方<p>元素的边距而崩溃。

我认为这很奇怪,因为他们处于不同的<divs>

我的解决方案是消除<p>底部的边距。在一侧有边距可防止第一个<p>底部的边距与第二个<p>的顶部折叠。

这种解决方法解决了我的问题,可能适用于其他人,但可能并不适用于所有人。

答案 9 :(得分:2)

css padding和jquery slideToggle不能很好地协同工作。尝试填充填充。

答案 10 :(得分:2)

我注意到,如果你的容器<br />后面有一个<div>,动画也会很跳跃。删除此解决了我的问题。

答案 11 :(得分:1)

尝试将容器的'position'属性(在本例中为.notice div)设置为'relative'。

为我工作。 资料来源:slideToggle height is "jumping"

答案 12 :(得分:1)

这里有很多建议,而且很多来回都是有效的。对我来说,行为问题是扩展容器的动画会过度扩展然后反弹回正确的扩展高度(所有这些都是作为一个动画的一部分完成的)。举例来说,动画最初会扩展到500px的高度,然后缩回到450px。崩溃没有问题。

有效的解决方案是添加到扩展/折叠div,一个CSS:    white-space:nowrap;

完美无缺 - 顺利扩展到正确的高度。

答案 13 :(得分: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] || { }));
};

答案 14 :(得分:1)

问题是您正在对父进行操作,这样做会删除与该元素相关的CSS。

您需要在note1上运行幻灯片,而不是注释1的父级。

我有同样的问题并通过向下移动来修复它。

答案 15 :(得分:0)

我遇到了同样的问题,但建议的解决方案中没有一个适用于我,所以我提出了一个解决方案,完全不依赖slideToggle()

Spark Notes :正常加载页面,收集要切换的每个元素的高度,将该高度存储在特殊数据属性中,然后折叠每个元件。然后就像更改元素的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/

答案 16 :(得分:0)

对我来说解决方案是,我有一个CSS样式定义如下:

* {
    transition: all .3s;
}

删除这是解决方案!

答案 17 :(得分:0)

如果你没有doctype,你可以尝试添加一个doctype,在我找到SO:jQuery slideToggle jumps around的建议后,它在IE8上为我工作。他提出了严格的DTD,但我刚刚使用了google.com使用的doctype <!doctype html>,它解决了我的问题。

答案 18 :(得分:0)

我通过设置解决了它:

box-sizing: content-box;

答案 19 :(得分:0)

添加我的解决方案:原来我的问题是flexbox(仅限chrome)。我在父元素上设置了align-self: center;。将@import "css/_variables.css"; 设置为我的slideToggling全角子元素,然后将其清除。大量使用两个小时。

答案 20 :(得分:0)

我刚刚了解到,如果expand / collapsing元素中有浮动元素,也会出现此问题。在这种情况下,动画元素末尾(仍在其中)的clearfix(clear:both;)可以摆脱它。

答案 21 :(得分:0)

我有同样的问题。我通过添加以下内容来修复它:

.delay(100)

猜猜给它更多时间思考有助于它吗?

答案 22 :(得分:0)

在我的情况下,我解决了将style="white-space:nowrap;"添加到元素中以防止对jQuery函数进行错误计算的问题;除非你需要换行,否则无需设置固定宽度。

答案 23 :(得分:0)

我正在使用slideDown()这样的

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

对我来说,它是主要的容器#content元素。我隐藏了它,然后调用slideDown()。我删除了CSS中的padding属性,之后一切正常。它通常是边距,填充或%宽度,因此最简单的方法是注释掉每个属性并逐个测试它们以获得结果。

答案 24 :(得分:0)

我遇到同样的错误需要几天时间才能找到解决方案。问题是当元素被隐藏时,jquery的高度越来越高。顶部修复它你必须在隐藏之前获得高度并使用自定义动画到那个高度。这很棘手的去here for a better explanation

答案 25 :(得分:0)

我的导航标签内有div的'jerkyness'也有同样的问题 - 我的目的是显示div悬停时的无序列表(如果存在)。我的列表是动态创建的,因此它们没有固定值。

继承人:

$("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");
  });
});

答案 26 :(得分:0)

今天进入这个问题,看到了这个问题,并根据我在这里看到的内容开始修修补补。我通过删除位置:相对于包含div的CSS来解决我们的跳跃问题。之后再没有那么古怪了。我的2美分。

答案 27 :(得分:0)

确保您没有在全局或容器或任何包含的元素上设置CSS转换规则。它也会引起急动。