用户交互触发的jQuery动画取决于先前的动画完成

时间:2013-09-06 06:19:00

标签: javascript jquery jquery-ui animation

我有一个可以通过点击zoom inzoom out按钮进行缩放的时间轴。此时间轴并非一次全部适合屏幕,因此它是一个可滚动的div。当用户点击缩放时,我希望时间轴中的位置相同,因此我为可滚动div计算新的scrollTop。这是我正在做的简化版本:

var self = this;
...
this.zoomIn = function() {
    var offset = $("#scrollable").scrollTop();
    self.increaseZoomLevel(); // Assume this sets the correct zoom level
    var newOffset = offset * self.zoomLevel();
    $("#scrollable").scrollTop(newOffset);
};

这很好用。现在我想为滚动设置动画。这个几乎有效:

var self = this;
...
this.zoomIn = function() {
    var offset = $("#scrollable").scrollTop();
    self.increaseZoomLevel(); // Assume this sets the correct zoom level
    var newOffset = offset * self.zoomLevel();
    $("#scrollable").animate({ scrollTop: newOffset });
};

如果点击一次就可以了。但是,如果在动画仍在运行时发生对zoomIn的第二次调用,则newOffset计算错误,因为在scrollTop()正确之前偏移设置为scrollTop(),因为动画仍在操纵它。

我试图以各种方式使用jQuery的队列来首先进行计算,这似乎有时会起作用:

var self = this;
...
this.zoomIn = function() {
    $("#scrollable").queue(function(next) {
        var offset = $("#scrollable").scrollTop();
        self.increaseZoomLevel(); // Assume this sets the correct zoom level
        var newOffset = offset * self.zoomLevel();
        next();
    }).animate({ scrollTop: newOffset });
};

我想我只是没有正确理解queue。即使重复快速调用zoomIn,我如何保持一切顺序?我想要:

zoomIn x 2次点击

给我:

计算1 - >动画1开始 - >动画1完成 - >计算2 - >动画2开始 - >动画2完成

而不是

计算1 - >动画1开始 - >计算2 - >动画1完成 - >动画2开始 - >动画2完成

因为然后动画2基于不正确的计算。

谢谢!

3 个答案:

答案 0 :(得分:1)

嗯......那么:stop(true,true)?请参阅:http://api.jquery.com/stop/

var self = this;
...
this.zoomIn = function() {
  var offset = $("#scrollable").stop(true,true).scrollTop();
  self.increaseZoomLevel(); // Assume this sets the correct zoom level
  var newOffset = offset * self.zoomLevel();
  $("#scrollable").animate({ scrollTop: newOffset });
};

答案 1 :(得分:1)

以下是@ RobinJonsson评论的实现,这也是我提出的解决方案,使用布尔值仅在上一个动画完成后才允许新的缩放操作:

var self = this;
...
this.zooming = false;
this.zoomIn = function() {
    if(!self.zooming){
        self.zooming = true;
        var offset = $("#scrollable").scrollTop();
        self.increaseZoomLevel(); // Assume this sets the correct zoom level
        var newOffset = offset * self.zoomLevel();
        $("#scrollable").animate({ scrollTop: newOffset },function(){
            self.zooming = false;
        });
    }
};

答案 2 :(得分:0)

我非常感谢给出的答案。它们都可以工作,但我的不成文要求包括动画完全完成以及没有点击损失。我知道,我的问题应该更彻底。

无论如何,我相信我有一个适合使用jQuery队列的两个要求的解决方案。有一些我没有意识到的关于排队的事情我学会了让我朝着正确的方向前进。最重要的是来自jQuery .animate docs:

  

使用自定义队列名称时,动画不会自动生成   启动...

这使我可以完全控制队列。我相信这与@ RobinJonsson的评论相似(或者可能正是如此)。

var top = 0;
var animating = false;

function calcAndAnimate(top) {
    $("#block").queue("other", function() {
        // Calculations go here
        animating = true;
        // This kicks off the next animation
        $("#block").dequeue("other");
    });
    $("#block").animate({
        top: top
    }, {
        duration: 2000,
        queue: "other",
        complete: function () {
            animating = false;
            // No need; it looks like animate dequeues for us, which makes sense.
            // So the next calculation will be kicked off for us.
            //$("#block").dequeue("other");
        }
    });
}

$("#queueButton").click(function() {
    top += 20;
    calcAndAnimate(top);
    if (!animating) {
        // Initial animation, need to kick it off
        $("#block").dequeue("other");
    }
});

有一个工作示例,其中包含显示http://jsfiddle.net/cygnl7/6h3c2/3/

强制订单的日志消息