为什么这个 canvas 动画在使用 ngRoute 第二次加载时挂起?
Why this canvas animation hangs when loaded for a second time with ngRoute?
问题
我正在使用 space invaders canvas animation 作为我的 404 未找到页面。当用户第一次被重定向到它时,它工作得很好,但如果用户第二次被重定向,动画就会挂起。
演示
我创建了一个 Plunker 示例来说明这个问题。页面从 /
位置开始加载 home.html。如果您单击“重定向到 /404”,该位置将更改为 /404
并加载 404.html。游戏动画运行没有问题
但是,如果您返回 /
(单击 link)并再次返回 /404
,动画将被挂起。此外,每秒帧数将从 60fps 降至 10fps。
代码
这个演示是用 AngularJS 构建的,我使用 ngRoute 切换页面,如下所示:(没有什么特别的)
$routeProvider.
when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
}).
when('/404', {
templateUrl: 'partials/404.html',
controller: '404Ctrl'
});
home.html 只包含指令,404.html 包含 canvas 元素:
<canvas id="game-canvas" width="600" height="400"></canvas>
Angular控制器启动动画调用initInvaders404();
。这个函数定义在 handle-game.js 里面。 game.js 完成了 canvas 动画代码,一旦 404.html 页面加载就执行。
我已经尝试过的
初步猜测:问题可能与使用其 ID 启动的 canvas 有关。当我重新创建 404.html 时,动画附加了以前的 ID,但没有附加新的 ID。为了对此进行测试,我创建了另一个 Plunker 并使用类似方法测试了另一个动画(蓝色矩形移动)。它工作正常,所以也许这不是问题所在。
第二次猜测:附加到canvas的动画代码只执行了一次,这就是为什么它第二次不起作用的原因。为了对此进行测试,我在控制器中放置了 game.js 和 handle-game.js 代码。不幸的是,同样的问题。 Plunker
第三个猜测: ngRoute 混淆了 canvas 元素。为了对此进行测试,我将 canvas 元素置于 ngView 之外,并将 ngShow 控制为 hide/show canvas。通过这种方法,问题就解决了。 initInvaders404();
可以被多次调用,但它总是聚焦在同一个元素上,永远不会被重新创建。 Plunker.
问题
为什么这个动画不能执行两次?
注1:我不想要变通解决方案(我已经在我的第三次猜测中找到了一个)。我想将 canvas 元素保留在 404.html 文件中。
注2:这个问题不是“请调试我的代码”(因为game.js有2000行代码)。我想了解的是,是否存在可能导致此问题的 canvas 属性 或 ngRoute 行为。
我发现可以第二次执行动画,但前提是第一个动画已经完成。在这种情况下,在游戏以 onWin()
或 onLoose()
事件结束后。
当 ngRoute 改变视图时,canvas 元素被销毁,但游戏循环仍在后台 运行s(我已经确认使用一些 console.log()
)。当我尝试将相同的游戏循环附加到相同的 canvas id 时,它挂起。
使用的解决方法是捕获 $locationChangeStart
事件并在 canvas 破坏之前停止动画。当我需要第二次执行游戏时,它会 运行: Plunker.
正在获取 $locationChangeStart
事件:
ctrls.controller(
'MyRootController',
function($location, $rootScope) {
$rootScope.$on("$locationChangeStart", function(event, next, current) {
var contains404 = current.includes("404");
if (contains404) { // if current is 404, next will be something else
stopInvaders404(); // code to stop the game loop before destroying the canvas
}
});
}
);
然而,第三方动画最简单的解决方案是将 canvas 放在 ngView
并控制其可见性:Plunker.
问题
我正在使用 space invaders canvas animation 作为我的 404 未找到页面。当用户第一次被重定向到它时,它工作得很好,但如果用户第二次被重定向,动画就会挂起。
演示
我创建了一个 Plunker 示例来说明这个问题。页面从 /
位置开始加载 home.html。如果您单击“重定向到 /404”,该位置将更改为 /404
并加载 404.html。游戏动画运行没有问题
但是,如果您返回 /
(单击 link)并再次返回 /404
,动画将被挂起。此外,每秒帧数将从 60fps 降至 10fps。
代码
这个演示是用 AngularJS 构建的,我使用 ngRoute 切换页面,如下所示:(没有什么特别的)
$routeProvider.
when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
}).
when('/404', {
templateUrl: 'partials/404.html',
controller: '404Ctrl'
});
home.html 只包含指令,404.html 包含 canvas 元素:
<canvas id="game-canvas" width="600" height="400"></canvas>
Angular控制器启动动画调用initInvaders404();
。这个函数定义在 handle-game.js 里面。 game.js 完成了 canvas 动画代码,一旦 404.html 页面加载就执行。
我已经尝试过的
初步猜测:问题可能与使用其 ID 启动的 canvas 有关。当我重新创建 404.html 时,动画附加了以前的 ID,但没有附加新的 ID。为了对此进行测试,我创建了另一个 Plunker 并使用类似方法测试了另一个动画(蓝色矩形移动)。它工作正常,所以也许这不是问题所在。
第二次猜测:附加到canvas的动画代码只执行了一次,这就是为什么它第二次不起作用的原因。为了对此进行测试,我在控制器中放置了 game.js 和 handle-game.js 代码。不幸的是,同样的问题。 Plunker
第三个猜测: ngRoute 混淆了 canvas 元素。为了对此进行测试,我将 canvas 元素置于 ngView 之外,并将 ngShow 控制为 hide/show canvas。通过这种方法,问题就解决了。 initInvaders404();
可以被多次调用,但它总是聚焦在同一个元素上,永远不会被重新创建。 Plunker.
问题
为什么这个动画不能执行两次?
注1:我不想要变通解决方案(我已经在我的第三次猜测中找到了一个)。我想将 canvas 元素保留在 404.html 文件中。
注2:这个问题不是“请调试我的代码”(因为game.js有2000行代码)。我想了解的是,是否存在可能导致此问题的 canvas 属性 或 ngRoute 行为。
我发现可以第二次执行动画,但前提是第一个动画已经完成。在这种情况下,在游戏以 onWin()
或 onLoose()
事件结束后。
当 ngRoute 改变视图时,canvas 元素被销毁,但游戏循环仍在后台 运行s(我已经确认使用一些 console.log()
)。当我尝试将相同的游戏循环附加到相同的 canvas id 时,它挂起。
使用的解决方法是捕获 $locationChangeStart
事件并在 canvas 破坏之前停止动画。当我需要第二次执行游戏时,它会 运行: Plunker.
正在获取 $locationChangeStart
事件:
ctrls.controller(
'MyRootController',
function($location, $rootScope) {
$rootScope.$on("$locationChangeStart", function(event, next, current) {
var contains404 = current.includes("404");
if (contains404) { // if current is 404, next will be something else
stopInvaders404(); // code to stop the game loop before destroying the canvas
}
});
}
);
然而,第三方动画最简单的解决方案是将 canvas 放在 ngView
并控制其可见性:Plunker.