如何使JQuery在旋转动画的循环中等待

4
我有一个圆形,里面有一个百分比文本,从0%开始。当我悬停在圆形上时,它会从0到100%(并围绕圆形产生另一种效果)。目前为止,百分比直接从0到100,但我想显示进度(0,1,2 ...,99,100),但我无法使JQuery在每个for迭代之间等待。
这是我尝试过的:JSFiddle演示
注意:我的代码现在只适用于Chrome。
这是一个迭代:
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)+"%");
}

我知道delay()需要排队,而html()不需要排队,所以我已经尝试使用setTimeout,但是它也没有起作用。我还尝试使用setInterval,请看下面的代码片段:

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

更明确地说,我希望百分比与效果进度相匹配 - 如果绕行的三角形行进了一半的路程,百分比应该是50,因此,当我不再悬停在圆圈上时,它应该逐渐回到0。

3个回答

6

首先,删除多余的transition: all 1s css规则!这会在所有解决方案中造成麻烦。

1. 教育性 - 使用setTimeout

for循环不会像你预期的那样工作,因为Javascript并不是用来进行这种主动等待循环的:

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

您需要使用超时和回调函数。禁用.delay函数调用,并按照以下示例将您的for循环重写为迭代的setTimeout回调函数:

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

反向旋转同样可以类比写出 - 你可以自己作为一项作业 :-)

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

2. 简单 - 使用jQuery .animate()

最简单的方法是使用jQuery .animate()函数,它会为您完成带有定时的动画"循环"。要对百分比文本进行动画处理,请使用progress回调。然而,动画旋转比较棘手,你需要使用一个特殊技巧

$({ 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/


1
你是对的,JavaScript不会逐行执行。而且你的代码仍然有漏洞。 - Kirk
谢谢,但这对我没有用。我更新了问题,以更清楚地说明我想要实现什么。 - Itay Gal
@ItayGal 这个问题是由于 transition: all 1s 的 CSS 规则引起的。我把它移除了,现在运行得很好。我更新了我的解决方案,并添加了一个更简单的使用 jQuery .animate() 的方法。 - Tomas
@Kirk,不知道你指的是哪个错误,但我猜现在没问题了吧? - Tomas
1
是的,之前在我悬停时,它会开始将数字增加到100,然后箭头才会移动。现在你绝对完美。 - Kirk
1
@Kirk 是的 - 通过删除那个可怕的 transition: all 1s CSS 规则,问题已经解决了。我根本没想到它会被 CSS 弄坏 :) - Tomas

3

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);
}

移除了 transition:all 1s。 在你的代码中,由于使用了 for 循环,盒子的百分比立即改变为 100%。for 循环将非常快速地执行,就好像它立即改变为 100%,因此不建议使用。


1
通常不建议直接引用其他答案。根据投票和被采纳的答案,顺序可能会改变。如果您需要引用特定的答案,最好是放置一个指向该答案的链接。此外,“上面的代码仍然有一些错误”并没有真正解释太多。如果您提供一些解释,特别是您修复了哪些错误以及为什么修复它们,那么这将是一个更好的答案。 - psubsee2003
你能加上一些解释吗?目前为止,你的解决方案更好,但缺乏适当的解释。虽然我理解它,但它不是一个“好”的stackoverflow答案。 - Itay Gal
这是抄袭 - 你从我的答案中拿走了我的小提琴,只是稍微用一些微不足道的更改更新了它!@ItayGal,你为什么接受这个? - Tomas
实际上它们并不那么相似,而且它可以工作,而你提出的解决方案则不能。你的答案包含更好的解释(为你投票),但是你提供的示例有错误 - 例如,如果我将鼠标悬停在圆圈上,然后在它到达100%之前没有悬停,动画会从100%开始倒计时,而不是所得到的百分比。另请参见:http://meta.stackexchange.com/questions/216655/which-answer-should-i-accept - Itay Gal

-1

你应该使用 setInterval,并且每次都要增加 percentage

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

你也可以在其中调用actions()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接