I'm developing an accordion plugin, and it's mostly done except for one bug where for the first few steps of the slideUp/slideDown, the accordion is 1px taller than it's meant to be, causing a visual bug. I've narrowed it down to the fact that the first step in the slideUp animation doesn't do anything, and I can't figure out why. Here's an example:

console.log('Start');
var diff = 0;
var upNow = 100;
var downNow = 0;
$.fx.interval = 1000;
var duration = $.fx.interval * 100;
$("#div1").slideUp({
  easing: 'linear',
  duration: duration,
  step: function(now) {
    if (now != 0 && now > 90) {
      console.log("Slide Up: " + now);
      upNow = now;
    }
  }
});

$("#div2").slideDown({
  easing: 'linear',
  duration: duration,
  step: function(now) {
    if (now != 0 && now < 10) {
      downNow = now;
      diff = 100 - (upNow + downNow);
      console.log("Slide Down: " + now);
      console.log("Slide Difference:" + diff);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style='height: 100px; background-color: red;' id='div1'>
</div>

<div style='height: 100px; background-color: blue; display: none;' id='div2'>
</div>

http://jsfiddle.net/hbh6U/

The problem is that I need these to be in sync, and I can't figure out why they're not, or how to get them in sync. One idea I've had is to skip the first step of the slideDown animation, but I'm not sure how to do that either. Has anyone got any ideas, or faced this bug before?

有帮助吗?

解决方案

The problem comes down to this line in jQuery's internal defaultPrefilter method:

tween.start = prop === "width" || prop === "height" ? 1 : 0;

This causes the animation for the second div (from 1px to 100px) to be shorter than that of the first div (from 0 to 100px).

To solve this modify your step function like this:

function linearStep(now, animation){
    var animationStart = animation.start;
    if (animationStart === 1){
         animationStart = 0;   
    }
    animation.now = (animation.end - animationStart ) * animation.pos + animationStart;
}

It overwrites the calculated now value by doing the same calculation with a fixed animationStart, which is 0 instead of 1.

This will break if the animation actually starts at 1, but there'd be other ways to handle it then.

Side-by-side Fiddle: http://jsfiddle.net/Nd3w2/3/

其他提示

i don't exactly know where is this issue coming from... Sunday morning... not too much time to investigate... But i found two possible solution based on your fiddle...

First one was to wrap these two DIVs in another DIV with overflow:hidden.

Second one... probably more appropriate is to call "slide" function only on one of the divs and then update the size of second one in callback, something like that:

console.log('Start');
var diff = 0;
var upNow = 100;
var downNow = 0;
$.fx.interval = 1000;
var duration = $.fx.interval * 100;
$("#div1").slideUp({ easing: 'linear', duration: duration, step: function(now)
{
    if(now != 0 && now > 90)
    {
        console.log("Slide Up: " + now);
        upNow = now;
    }

    $("#div2").height(100-  $("#div1").height());
}});

Also remove "disply:none" form div2 styles...

It fixes the issue and is a bit more elegant solution in my opinion... Calling two separate animation functions can lead to possible sync problems... Hope that helps...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top