1

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

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,我如何保持一切井井有条?我想:

zoomInx 2 次点击

给我:

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

并不是

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

因为那么 animate 2 是基于不正确的计算。

谢谢!

4

3 回答 3

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 });
};
于 2013-09-06T06:28:29.740 回答
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;
        });
    }
};
于 2013-09-06T08:11:20.290 回答
0

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

无论如何,我相信我有一个使用 jQuery 队列同时满足这两个要求的解决方案。有几件事我没有意识到我了解到的队列让我朝着正确的方向前进。最重要的是来自 jQuery.animate文档:

使用自定义队列名称时,动画不会自动开始...

这使我可以完全控制队列。我相信这类似于(或者可能正是)@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/有一个显示强制顺序的日志消息的工作示例

于 2013-09-06T17:00:29.167 回答