Aftab Ansari
Aftab Ansari

Reputation: 87

CSS rotate animation in while-loop works only once

I want a div tag in html to rotate, when I click on that. Here is my code

$(document).on('click', '.rotate', function() {
    degrees = 0;
    while (degrees >= (-1080)) {
        $(this).css({
            'transform': 'rotate(' + degrees + 'deg)'
        }).css({
            'transition': '3s'
        });
        degrees--;
    }
});
.rotate {
    position: relative;
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: linear-gradient(magenta, blue, cyan, magenta);
    margin: 100px auto;
    line-height: 100px;
    cursor: pointer;
    border: 1px solid #fff;
}

.center {
    width: 30px;
    height: 30px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.7);
    z-index: 5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rotate">
    <div class="center"></div>
</div>

It works good on first click. But in second and later clicks it doesn't. I don't know why this is happening.

Upvotes: 3

Views: 866

Answers (2)

Tomalak
Tomalak

Reputation: 338158

You don't really want to have jQuery do the animation in a while loop to begin with.

Let CSS do the animation, and only use jQuery to wire up the event handler and make sure the rotation animation will not stack.

$(document).on('click', '.rotate:not(.rotating)', function () {
    var $this = $(this);
    $this.addClass("rotating");
    setTimeout(function () {
        $this.removeClass("rotating")
    }, 3000);
});
.rotate {
  height: 50px;
  width: 50px;
  text-align: center;
  border: 1px solid blue;
  padding: 5px;
  margin: 5px;
  display: inline-block;
} 
.rotating {
  transform: rotate(-1080deg);
  transition: 3s;
  border-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="rotate">rotate 1</div>
<div class="rotate">rotate 2</div>
<div class="rotate">rotate 3</div>
<div class="rotate">rotate 4</div>

Upvotes: 2

Terry
Terry

Reputation: 66103

There is no need to use a while loop: CSS will handle the animations directly, and you don't have to set the degree at every single step.

The actual reason why the animation does not run again after the first click is because you are always animating to -1080deg, which means that after the first run, you will stop changing the value, since it is already at -1080deg: since the value never changes, the CSS animation will not run again because the browser does not see any difference, and will choose not to tween anything.

What you want is to decrement the degree at every count/click. This can be done by storing the number of clicks, and then increment it at every click. Then, the amount of degree you want to rotate will be a multiple of that count:

let count = 0;
$(document).on('click', '.rotate', function() {
  count++;
  degrees = -1080 * count;
  $(this).css({
    'transform': 'rotate(' + degrees + 'deg)'
  }).css({
    'transition': '3s'
  });
});
.rotate {
  position: relative;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: linear-gradient(magenta, blue, cyan, magenta);
  margin: 100px auto;
  line-height: 100px;
  cursor: pointer;
  border: 1px solid #fff;
}

.center {
  width: 30px;
  height: 30px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.7);
  z-index: 5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rotate">
  <div class="center"></div>
</div>

Upvotes: 4

Related Questions