javascript - 为什么这个 Canvas 动画在使用 ngRoute 第二次加载时挂起?

标签 javascript angularjs html5-canvas ngroute

问题

我正在使用 space invaders canvas animation作为我的 404 未找到页面。当用户第一次被重定向到它时,它工作得很好,但如果用户第二次被重定向,动画就会挂起。


演示

我创建了一个 Plunker显示问题的示例。该页面从加载 home.html 的 / 位置开始。如果您单击“重定向到/404”,该位置将更改为 /404 并且将加载 404.html。游戏动画将正常运行。

但是,如果您返回到 /(单击链接)并再次返回到 /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 Controller 启动动画调用 initInvaders404();。此函数在 handle-game.js 中定义。 game.js 完成 404.html 页面加载后立即执行的 Canvas 动画代码。


我已经尝试过的

初步猜测:问题可能与使用其 ID 启动的 Canvas 有关。当我重新创建 404.html 时,动画附加了以前的 ID,但没有附加新的 ID。为了对此进行测试,我创建了另一个 Plunker并用类似的方法测试了另一个动画(蓝色矩形移动)。它工作正常,所以也许这不是问题所在。

第二次猜测:附加到 Canvas 的动画代码只执行一次,这就是为什么它不能第二次工作的原因。为了对此进行测试,我将 game.js 和 handle-game.js 代码放入了 Controller 中。不幸的是,同样的问题。 Plunker

第三个猜测: ngRoute 干扰了 canvas 元素。为了对此进行测试,我将 Canvas 元素放置在 ngView 之外并控制 ngShow 以隐藏/显示 Canvas 。通过这种方法,问题就解决了。 initInvaders404(); 可以被调用多次,但它总是聚焦于同一个元素,并且永远不会被重新创建。 Plunker .


问题

为什么这个动画不能执行两次?

注意 1: 我不想要变通解决方案(我已经在第三次猜测中找到了一个)。我想将 canvas 元素保留在 404.html 文件中。

注意 2: 这个问题不是“请调试我的代码”(因为 game.js 有 2000 行代码)。我想了解的是,是否存在可能导致此问题的 canvas 属性或 ngRoute 行为。

最佳答案

我发现可以第二次执行动画,但前提是第一个动画已经完成。在这种情况下,游戏结束后会发生 onWin()onLoose() 事件。

当 ngRoute 改变 View 时,canvas 元素被销毁,但游戏循环仍在后台运行(正如我使用一些 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 .

关于javascript - 为什么这个 Canvas 动画在使用 ngRoute 第二次加载时挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31495103/

相关文章:

html5-canvas - 如何使用 kinetic js 在 Canvas 中的文本上添加文本转换?

node.js - 如何在nest js中实现guard的集成测试?

javascript - 如何使用 forEach 从 ng-repeat 中删除 json 对象

javascript - Github Pages 仅在选项卡之间切换时重新加载

javascript - 第一次尝试时未显示崩溃中的 Bootstrap 下拉菜单

javascript - ngCache与Webpack,ES6不输出模板html,解析错误

Qt (QML) 虚线圆

javascript - 尝试旋转图像,同时保持图片的纵横比

javascript - 我可以使用 nextUntil 来获取这些值吗?

javascript - Google map 信息窗口显示在错误的 map 上