确保动画实际发生的唯一方法是longRunningMethod
定期向浏览器屈服。UI 渲染线程阻塞 JavaScript 线程的情况并不少见,因此您对 DOM 所做的更改要等到下次 JavaScript 线程退出时才会显示。您可以通过调用setTimeout
超时0
(在大多数浏览器实现上显然会超过 0 毫秒;许多将该值限制为至少 4 毫秒,可能高达 10 毫秒)。
示例:这是一个添加 500 个 div 的脚本,但浏览器没有机会显示正在进行的工作或(通常)动画任何内容:
jQuery(function($) {
$("#btnGo").click(function() {
var n;
display("Loading...");
for (n = 0; n < 500; ++n) {
$("<div/>").html("Div #" + n).appendTo(document.body);
}
display("Done loading");
function display(msg) {
$("<p/>").html(msg).appendTo(document.body);
}
});
});
实时示例*带有微调器图形的示例
如您所见,它永远不会产生,因此当您单击按钮时,页面会冻结片刻,然后出现所有 500 个 div 和消息。
与频谱的另一端形成对比,它在每个 div之间产生:
jQuery(function($) {
$("#btnGo").click(function() {
display("Loading...");
addDivs(0, 500, function() {
display("Done loading");
});
function addDivs(current, max, callback) {
if (current < max) {
$("<div/>").html("Div #" + current).appendTo(document.body);
setTimeout(function() {
addDivs(current + 1, max, callback);
}, 0);
}
else {
callback();
}
}
function display(msg) {
$("<p/>").html(msg).appendTo(document.body);
}
});
});
实时示例*带有微调器图形的示例
由于这会产生,您可以看到正在进行的工作。
您可能会注意到,第二个脚本需要更长的时间,甚至可能更长的时间才能实时获得相同的结果。这是因为产量需要时间,浏览器更新显示也是如此。在实践中,您会希望在第一个示例和第二个示例之间找到一个平衡点——这样的结果经常足以显示进度,但又不会经常导致该过程需要花费不必要的长时间才能完成。