使用ngRoute第二次加载时,为什么这个画布动画会挂起? [英] Why this canvas animation hangs when loaded for a second time with ngRoute?

查看:143
本文介绍了使用ngRoute第二次加载时,为什么这个画布动画会挂起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用太空入侵者画布动画作为我的404未找到的页面。当用户第一次被重定向到它时它工作得非常好,但是如果再次重定向用户,则动画会挂起。

I'm using a space invaders canvas animation as my 404 not found page. It is working pretty fine when the user is redirected to it for the first time, but the animation hangs if the user is redirected a second time.


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

I've created a Plunker example to show the issue. The page starts at the / location loading the home.html. If you click on "Redirect to /404", the location will be changed to /404 and 404.html will be loaded. The game animation will be running without problems.

但是,如果你回到 / (点击链接)并再次回到 / 404 ,动画将被绞死。此外,每秒帧数将从60fps降至10fps。

However, if you go back to / (clicking in the link) and back again to /404, the animation will be hanged. Also, the frames-per-second will drop from 60fps to 10fps.


这个演示是使用AngularJS构建的,我使用ngRoute切换页面如下:(没什么特别之处)

This demo was built with AngularJS and I switch pages using ngRoute like the following: (nothing special in this)

$routeProvider.
    when('/', {
        templateUrl: 'partials/home.html',
        controller: 'HomeCtrl'
    }).
    when('/404', {
        templateUrl: 'partials/404.html',
        controller: '404Ctrl'
    });

home.html仅包含说明,404.html包含canvas元素:

The home.html contains just instructions and 404.html contains the canvas element:

<canvas id="game-canvas" width="600" height="400"></canvas>

Angular Controller启动动画,调用 initInvaders404(); 。此函数在handle-game.js中定义。 game.js完成加载404.html页面后立即执行的画布动画代码。

The Angular Controller starts the animation calling initInvaders404();. This function is defined inside handle-game.js. The game.js completes the canvas animation code that is executed as soon as the 404.html page is loaded.


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

First guess: the issue may be related with the canvas being started using its ID. When I recreate the 404.html, the animation is attached with the previous ID but not with the newer ID. To test this, I've created another Plunker and tested another animation (blue rectangle moving) with a similar approach. It is working fine, so maybe that's not the problem.

第二个猜测:附加到画布的动画代码只执行一次,这就是它第二次不起作用的原因。为了测试这个,我在控制器中放置了game.js和handle-game.js代码。不幸的是,同样的问题 Plunker

Second guess: the animation code that is attached to the canvas is executed only once, that's why it does not work a second time. To test this, I've placed the game.js and handle-game.js code inside the controller. Unfortunately, same issue. Plunker

第三个猜测: ngRoute正在搞乱canvas元素。为了测试这个,我将canvas元素放在ngView之外并控制ngShow来隐藏/显示画布。通过这种方法,问题得以解决。可以多次调用 initInvaders404(); ,但它始终会聚焦在同一个元素中,并且永远不会重新创建它。 Plunker

Third guess: ngRoute is messing with the canvas element. To test this, I've placed the canvas element out of the ngView and controlled the ngShow to hide/show the canvas. With this approach, the problem was solved. The initInvaders404(); can be called multiple times, but it will always focus in the same element and it will never be recreated. Plunker.


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

Why this animation can't be executed two times?

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

Note1: I do not want a workaround solution (I've already found one in my third guess). I would like to keep the canvas element inside the 404.html file.

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

Note2: this question is not a "please, debug my code" (since game.js have 2000 lines of code). What I want to understand is if there is a canvas property or ngRoute behavior that may cause this.

推荐答案

我发现了可以第二次执行动画,但仅在第一个动画完成时才执行。在这种情况下,游戏结束后用 onWin() onLoose()事件。

I've found that it is possible to execute the animation for a second time, but only if the first animation has finished. In this case, after the game finished with an onWin() or onLoose() event.

当ngRoute更改视图时,canvas元素被销毁,但游戏循环仍然在后台运行(因为我已经确认使用了一些 console.log())。当我尝试将相同的游戏循环附加到相同的画布ID时,它会挂起。

When ngRoute changes the view, the canvas element is destroyed, but the game loop still runs in background (as I've confirmed using some console.log()). When I try to attach the same game loop to the same canvas id, it hangs.

使用的解决方法是捕获 $ locationChangeStart 事件并在画布销毁之前停止动画。当我需要第二次执行游戏时,它将运行: Plunker

The workaround used was to catch the $locationChangeStart event and stop the animation before the canvas destruction. When I need to execute the game for a second time, it will run: 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
        }
    });
  }
);

但是,第三方动画的最简单解决方案,不涉及更改动画代码(正如我对 stopInvaders404()所做的那样,是将画布从 ngView 中取出并控制其可见性:< a href =http://plnkr.co/edit/6y7blPzQ8TLXgxs6yepF?p=preview =nofollow> Plunker 。

However, the simplest solution for a third-party animation, which does not involve changing the animation code (as I did with the stopInvaders404()) is to place the canvas out of the ngView and control its visibility: Plunker.

这篇关于使用ngRoute第二次加载时,为什么这个画布动画会挂起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆