jQuery 切换标签时动画功能中断
jQuery animation function breaks when switching tabs
更新: 我在 plunkr 中重现了错误:请参阅 http://plnkr.co/BpYfCNBESUT6ZkiSZHgx
当您执行以下操作时出现问题:
打开 website。刷新网站,当您看到页面正在浏览器选项卡中加载时,when you see the spinner in the tab
。
切换到浏览器中的另一个选项卡。如果它没有发生。再试一次。如果按照所说的去做,您很可能会看到这个:
你可能会说,this is not such a big deal, you have to be real fast to let this error happen
。然而,想象一下连接速度较慢的人,他转到浏览器中的另一个选项卡,继续观看他的 YouTube 视频,同时网站正在加载。当他回来时,他只看到页面一直在加载。
让我们假设这个 animation
代码:
$pageloaderbar.animate({
width: "46%"
}, {
duration: 700,
complete: function () {
$scope.continue();
}
});
当第一个 animation
完成时,它会调用一个名为 $scope.continue();
的新函数。看起来像这样:
$scope.continue = function () {
$timeout(function () {
$pageloaderbar.animate({
width: "100%"
}, {
duration: 500,
complete: function () {
$scope.PageIsLoading = false;
}
});
});
}
问题是,当用户在浏览器中切换选项卡时,在 $pageloaderbar.animate
和 $scope.continue
之间,$plageloaderbar.animate
函数永远不会到达 complete
函数。浏览器控制台显示如下错误(Chrome)
我的问题是,如何查看用户是否在网站上 active
?或者,即使用户不是 browser tab
上的 active
,我如何仍然执行该功能?
因为好像没有人带遮阳篷,所以我自己想了一个小办法。但是,如果有人仍然可以解释为什么 animation
在切换标签时中断,我很高兴。
解决方法非常简单,我只需添加这段代码。
complete: function () {
if(document.hidden) {
$(window).on("blur focus", function () {
$scope.continue();
});
} else {
$scope.continue();
}
}
而不是:
complete: function () {
$scope.continue();
}
$scope.continue = function () {
$timeout(function () {
$pageloaderbar.animate({
width: "100%"
}, {
duration: 500,
complete: function () {
$scope.PageIsLoading = false;
$("body").css("overflow", "auto");
$pageloaderwrap.addClass("page-loader-finished");
$scope.pageReady();
}
});
});
}
var $pageloaderwrap = $(".page-loader-wrap");
var $pageloader = $(".page-loader");
var $pageloaderbar = $(".page-loader .page-loader-bar");
$("body").css("overflow", "hidden");
$pageloaderbar.animate({
width: "46%"
}, {
duration: 700,
complete: function () {
if (document.hidden) {
$(window).on("blur focus", function () {
$scope.continue();
});
} else {
$scope.continue();
}
}
});
尝试在调用 $pageloaderbar.animate 之前定义您的 continue 函数。这可能不是主要问题,但总是有可能因此而出现问题。
你的解决方案只是一个补丁,不是真正的解决方案,看起来也不是很好。即使它解决了你的问题,你也必须找到某种方法来防止这个错误。
我强烈建议你离开jquery。此类问题通常来自 jquery - angular 不兼容。
在 chrome 的较新版本中,这与选项卡的可见性有关,您的功能因此而中断。您可以使用可见性 API 来了解该选项卡是否对用户可见。
请看一下我发现的 link:
这是由 jQuery animate
函数引起的,该函数将动画选项对象传递给名为 speed
的函数。此函数检查 document
是否为 hidden
- 如果选项卡处于非活动状态,则为 hidden
。如果隐藏,(或者fx.off
设置为true
),所有动画持续时间设置为0
.
您可以在 plunkr 的 jQuery 文件中的 7137
行看到这个。
if ( jQuery.fx.off || document.hidden ) {
opt.duration = 0;
由于动画现在没有持续时间,它变为同步,因此您的 complete
函数在调用 animate
之后出现的事实是一个问题。
要解决此问题,您需要将 complete
函数声明移到对 animate
.
的调用上方
更新: 我在 plunkr 中重现了错误:请参阅 http://plnkr.co/BpYfCNBESUT6ZkiSZHgx
当您执行以下操作时出现问题:
打开 website。刷新网站,当您看到页面正在浏览器选项卡中加载时,when you see the spinner in the tab
。
切换到浏览器中的另一个选项卡。如果它没有发生。再试一次。如果按照所说的去做,您很可能会看到这个:
你可能会说,this is not such a big deal, you have to be real fast to let this error happen
。然而,想象一下连接速度较慢的人,他转到浏览器中的另一个选项卡,继续观看他的 YouTube 视频,同时网站正在加载。当他回来时,他只看到页面一直在加载。
让我们假设这个 animation
代码:
$pageloaderbar.animate({
width: "46%"
}, {
duration: 700,
complete: function () {
$scope.continue();
}
});
当第一个 animation
完成时,它会调用一个名为 $scope.continue();
的新函数。看起来像这样:
$scope.continue = function () {
$timeout(function () {
$pageloaderbar.animate({
width: "100%"
}, {
duration: 500,
complete: function () {
$scope.PageIsLoading = false;
}
});
});
}
问题是,当用户在浏览器中切换选项卡时,在 $pageloaderbar.animate
和 $scope.continue
之间,$plageloaderbar.animate
函数永远不会到达 complete
函数。浏览器控制台显示如下错误(Chrome)
我的问题是,如何查看用户是否在网站上 active
?或者,即使用户不是 browser tab
上的 active
,我如何仍然执行该功能?
因为好像没有人带遮阳篷,所以我自己想了一个小办法。但是,如果有人仍然可以解释为什么 animation
在切换标签时中断,我很高兴。
解决方法非常简单,我只需添加这段代码。
complete: function () {
if(document.hidden) {
$(window).on("blur focus", function () {
$scope.continue();
});
} else {
$scope.continue();
}
}
而不是:
complete: function () {
$scope.continue();
}
$scope.continue = function () {
$timeout(function () {
$pageloaderbar.animate({
width: "100%"
}, {
duration: 500,
complete: function () {
$scope.PageIsLoading = false;
$("body").css("overflow", "auto");
$pageloaderwrap.addClass("page-loader-finished");
$scope.pageReady();
}
});
});
}
var $pageloaderwrap = $(".page-loader-wrap");
var $pageloader = $(".page-loader");
var $pageloaderbar = $(".page-loader .page-loader-bar");
$("body").css("overflow", "hidden");
$pageloaderbar.animate({
width: "46%"
}, {
duration: 700,
complete: function () {
if (document.hidden) {
$(window).on("blur focus", function () {
$scope.continue();
});
} else {
$scope.continue();
}
}
});
尝试在调用 $pageloaderbar.animate 之前定义您的 continue 函数。这可能不是主要问题,但总是有可能因此而出现问题。
你的解决方案只是一个补丁,不是真正的解决方案,看起来也不是很好。即使它解决了你的问题,你也必须找到某种方法来防止这个错误。
我强烈建议你离开jquery。此类问题通常来自 jquery - angular 不兼容。
在 chrome 的较新版本中,这与选项卡的可见性有关,您的功能因此而中断。您可以使用可见性 API 来了解该选项卡是否对用户可见。
请看一下我发现的 link:
这是由 jQuery animate
函数引起的,该函数将动画选项对象传递给名为 speed
的函数。此函数检查 document
是否为 hidden
- 如果选项卡处于非活动状态,则为 hidden
。如果隐藏,(或者fx.off
设置为true
),所有动画持续时间设置为0
.
您可以在 plunkr 的 jQuery 文件中的 7137
行看到这个。
if ( jQuery.fx.off || document.hidden ) {
opt.duration = 0;
由于动画现在没有持续时间,它变为同步,因此您的 complete
函数在调用 animate
之后出现的事实是一个问题。
要解决此问题,您需要将 complete
函数声明移到对 animate
.