Itay Gal
Itay Gal

Reputation: 10824

How to make JQuery wait inside a loop in rotation animation

I have a circle and in it a percentage text, starts with 0%. Once I hover the circle it goes from 0 to 100% (with another effect around the circle). As for now, the percentage goes from 0 to 100 directly and I want it to show the progress (0,1,2...,99,100) but I can't manage to make JQuery wait between each for iteration.

This is what I've tried: JSFiddle demo.

Note: My code works with chrome for now.

That's one iteration:

function actions(i){
    var box = $('#box');
    box.css('transform','rotate(' + i + ' deg)');
    box.css('-ms-transform','rotate(' + i + 'deg)');
    box.css('-webkit-transform','rotate(' + i + 'deg)');
    prec = (100*(i + 135))/360;
    $("div.prec").delay(100).html(Math.round(prec)+"%");
}

I understand that delay() needs to be queued and html() is not queued so I already tried setTimeout, but that it didn't work either. I also tried setInterval - see the next code snippet:

setInterval(function () {
    $("div.prec").html(Math.round(prec)+"%");
},100);

To be more clear, I want the percentage to fit the effect progress - if the triangle that goes around travels half of the way, the percentage should be 50, and so, when I'm not hovering the circle anymore it should gradually go back to 0.

Upvotes: 4

Views: 1414

Answers (3)

user2467577
user2467577

Reputation:

http://jsfiddle.net/NNq3z/13/

var i = -135,box = $("#box"),prec;
setTimeout(function(){
if($("#circle").is(":hover"))
   loopit("c");
else
    loopit("nc");
},1);
function loopit(dir){
if (dir=="c")
    i++;        
else
    i--;
if(i<-135)
    i=-135;
if(i>225)
    i=225;
prec = (100*(i + 135))/360;   
$(".prec").html(Math.round(prec)+"%");
box.css("transform","rotate("+i+"deg)")
.css("-ms-transform","rotate("+i+"deg)")
.css("-moz-transform","rotate("+i+"deg)")
.css("-webkit-transform","rotate("+i+"deg)");
setTimeout(function(){
if($("#circle").is(":hover"))
   loopit("c");
else
    loopit("nc");
},1);
}

Removed transition:all 1s. In your code, the percentage of the box immediately change to 100% because you use for loop. For loop will be executed very fast as if it immediately change to 100% so it is not recommended.

Upvotes: 3

Tomas
Tomas

Reputation: 59597

First, remove the surplus transition: all 1s css rule! This is making trouble in all the solutions.

1. Educational - using setTimeout

The for loop will not work as you expect, javascript is not build for active-wait loop like this:

for (var i = -135; i < 225; i++){
    actions(i);
    sleep(some time);      
}

You have to use timeout and callbacks. Disable the .delay function call and rewrite your for loop to iterative setTimeout callback as shown here:

function loopit(dir, i){
    if (typeof i == "undefined") 
        i = -135;
    if (i >= 225)
        return;
    actions(i);
    setTimeout(function () {
        loopit(dir, i + 1);
    }, 1);
}

The back-rotation would be written analogically - you can write it yourself as a homework :-)

http://jsfiddle.net/NNq3z/10/

2. Easy - using jQuery .animate()

The easiest way is to use jQuery .animate() function, that will do the animation "loop" with timing for you. To animate the percent text, use progress callback. Animating rotation is tricky though, you need to use special trick:

$({ deg: deg_from } ).animate({
    deg: deg_to
}, {
    duration: 1000,
    progress: function (animation, progress) {
        $("div.prec").html(Math.round(progress*100)+"%");
    },
    step: function(now) {
        $('#box').css({
            transform: 'rotate(' + now + 'deg)'
        });
    }
});

http://jsfiddle.net/q9VXC/1/

Upvotes: 6

Barmar
Barmar

Reputation: 782785

You should use setInterval, and you have to increment percentage each time:

var percentage = 0;
var timer = setInterval(function() {
    percentage++;
    if (percentage > 100) {
        clearInterval(timer);
    } else {
        $("div.prec").html(percentage + "%");
    }
}

You could also call actions() inside there.

Upvotes: -1

Related Questions