简体   繁体   中英

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.

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/

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM