Home » Jquery » javascript – Why does a CSS transition not work well with another animation based on jQuery's animate method?-Exceptionshub

javascript – Why does a CSS transition not work well with another animation based on jQuery's animate method?-Exceptionshub

Posted by: admin February 24, 2020 Leave a comment

Questions:

I have a button that I wish to move when it is clicked, and while moving it should also flip. So there are two animations that take place at the same time, and have the same duration. I also have a CSS transition set up for all the properties of the button. It seems to me that only the CSS scale transform works when I use both jQuery’s animate method and the CSS transition effect. When I remove one of the animations, the other one works well.

// find elements
var button = $("button");

// handle click
button.on("click", function() {
  button.css({
    "transform": "scaleX(0)"
  });
  
	// the bug: the following animation is not visible
  button.animate({
    "top": "-100px" // I tried without "px" too
  }, 0.15 * 1000);
});
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
  
  position: relative;
  transition: all 0.15s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <p>Hello World</p>
  <button>Click me</button>
</div>

The JSFiddle is here.

Thank you.

How to&Answer:

When you declare your button style as transition: all 0.15s; that is affecting the top property too. Therefore, in your flow:

  1. The top animation does happen a few ms after the css manipulation
  2. Every step of the top animation is subject to a transition

Due to the first, there’s already a racing condition that may cause the top animation to go unnnoticed, but due to the second, there’s also an easing over every step of jQuery’s animation.

If not provided, $.fn.animate easing function defaults to swing which is defined as:

 function( p ) {
    return 0.5 - Math.cos( p * Math.PI ) / 2;
 }

Where p is between 0 and 1.

In this case, you’re asking jQuery to change top from 0 to -100 in 150ms. Usually the animation interval is around 13ms, but let’s say it’s exactly 15ms so we have 10 animation steps. Due to the swing easing, the first step amounts for:

 100 * (0.5 -  Math.cos( (0.1 * Math.PI ) / 2) = 2.45

In other words, due to transition: all 0.15s and leaving the race condition apart, clicking the button would scale it horizontally to 0 and move it 2.45px upwards in 0.15s.

If, instead, you only transition the transform property, and leave the top transition to jQuery, you could see both of them happening in parallel.

In the following snippet I slowed things down to take 1s, added console statements on each step and included the regular button, another one that only transitions transform and a third one that transitions transform and top which doesn’t use jQuery animations.

// find elements
var button = $("button.animate");

// handle click
button.on("click", function() {
  console.clear();

  $(this).css(
    "transform", (index, value) => {
      console.log(`top: transform was ${value}`);
      return "scaleX(0)";
    }
  );

  console.log('before $.fn.animate');
  $(this).animate({
    "top": "-100px"
  }, 1000, 'swing', () => {
    console.log('finish animation');
    window.setTimeout(() => {
      console.log('restore initial state')
      $(this).css({
        transform: "unset",
        top: 0
      });
    }, 2000);
  });



});

// handle click
$("button.no_animate").on("click", function() {
  console.clear();

  $(this).css({
    "transform": "scaleX(0)",
    "top": "-100px"
  });

  window.setTimeout(() => {
    console.log('restore everything');
    $(this).css({
      transform: "unset",
      top: 0
    });
  }, 2000);

});
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

p {
  color: white;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
  position: relative;
}

button.animate.all {
  transition: all 1s;
}

button.animate.transform {
  transition: transform 1s;
}

button.no_animate {
  top: 0;
  transition: top 1s, transform 1s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <p id="check">Hello World</p>
  <button class="animate all">I Transition all</button>
  <button class="animate transform">I Transition "transform" </button>
  <button class="no_animate transform">I don't use animate </button>
</div>

Answer:

Use only the required property in transition i.e. transform 0.15s instead of all 0.15s

// find elements
var button = $("button");

// handle click
button.on("click", function() {
  button.css({
    "transform": "scaleX(0)"
  });
  
	// the bug: the following animation is not visible
  button.animate({
    "top": "-100px" // I tried without "px" too
  }, 0.15 * 1000);
});
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;

  position: absolute;
  transition: transform 0.15s; /* change here*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <p>Hello World</p>
  <button>Click me</button>
</div>

Answer:

Please see the code on JS fiddle for smooth animation:

https://jsfiddle.net/harshsetia/tvcb4mso/8/

Answer:

your button position should bet set to absolute!

var button = $("button");

// handle click
button.on("click", function() {
  button.css({
    "transform": "scaleX(0)"
  });

    // the bug: the following animation is not visible
  button.animate({top: "-100px"}, 0.15 * 1000);
});
button{
  position:absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <p>Hello World</p>
  <button>Click me</button>
</div>