繁体   English   中英

想要使用clearInterval停止setInterval,但无济于事

[英]Wanting to stop setInterval using clearInterval, but to no avail

我所拥有的是一个与keydown事件相关联的元素。

类似问题的答案都指向clearInterval,我无法开展工作。

首先,我使用keyup事件来检查按下了哪个箭头键:

var counter = 0;

var yPosArray = [];
var right = true;
var done = false;
var leftX;
var rightX;
$(document).keydown (function(e) 
{
    rightX = parseInt(($('#movingObject').css('left')).replace('px','')) + 50;
    leftX = parseInt(($('#movingObject').css('left')).replace('px',''));

    if(e.which == 39)// right
    {
        $('#movingObject').find('img').attr('src','assets/images/mario_right.png');
        right = true;
        $('#xRight').val(rightX);
        $('#xLeft').val(leftX);
        move();
    }
    if(e.which == 37)   //left  
    {
        $('#movingObject').find('img').attr('src','assets/images/mario_left.png');
        right = false;
        $('#xRight').val(rightX);
        $('#xLeft').val(leftX);
        move();
    }
    if(e.which == 38)   //up    
    {
        if($('#movingObject').css('bottom') == '0px' && !false)
        {
            done = true;
            gravity();
            done = false;
        }
    }
});

如上面看到的,当这种条件下, e.which == 37 ,被满足,则该方法move()被调用。 move方法的作用如下所示是增加元素的left样式属性。 我有一个计时器的原因是随着时间的推移速度增加,但是当钥匙被释放时,事件应该停止射击。 因此,我想调用keyup事件,如上一个代码片段所示。 解释将在那里继续。

var speed = 0;
var maxspeed = 0;
var timer;
function move()
{   
     var counter = 0;
     timer = setInterval(function () 
     {
         maxspeed++;
         $('#movingObject').css('left', moveX + maxspeed + 'px');
         ++counter;
    }, 70);
}

如上所示,timer变量是在创建move函数之前声明的,其中它被设置为setInterval方法。 因为变量在根级别,如果这是有意义的,它可以在所有函数中使用。

如下所示,我已启动keyup事件以检查不同的键。

$(document).keyup (function(e) 
{
    var posX = parseInt(($('#movingObject').css('left')).replace('px',''));
    if(e.which == 39)// right
    {
        maxspeed = 0;
        clearInterval(timer);
        timer = 0;
    }
    if(e.which == 37)   //left  
    {
        maxspeed = 0;
        clearInterval(timer);
        timer = 0;
    }
    $('#movingObject').css('left', posX + 'px');
});

上面,我使用了clearInterval并尝试将timer设置为0,然后继续增加。

这是我的代码结构的所有脚本的小提琴

任何想法为什么会这样?

每次setInterval都会创建一个新的timer ,所以当你clearInterval你必须清除你创建的所有计时器(可能是其中一些)。看看这个打击:

var speed = 0;
var maxspeed = 0;
var timer=[];
function move()
{   
     var counter = 0;
     timer.push(setInterval(function () 
     {
         maxspeed++;
         $('#movingObject').css('left', moveX + maxspeed + 'px');
         ++counter;
    }, 70));
}

$(document).keyup (function(e) 
{
    var posX = parseInt(($('#movingObject').css('left')).replace('px',''));
    if(e.which == 39)// right
    {
        maxspeed = 0;
        $.each(timer,function(i,n){
            clearInterval(n);
        });
        timer=[];
    }
    if(e.which == 37)   //left  
    {
        maxspeed = 0;
        $.each(timer,function(i,n){
            clearInterval(n);
        });
        timer=[];
    }
    $('#movingObject').css('left', posX + 'px');
});

当用户同时按下两个(或更多)键时,可能会发生这种情况。 然后你将调用move()然后在两者之间没有键盘清除一个间隔 - 这意味着你要覆盖第一个的timer间隔id并且永远不能再次停止它,基本上在密钥时忘记了它发生。

怎么解决这个? 有一些选择:

  • 一次只运行一个间隔。 这可以通过在每个timer = setInterval(…)使用clearInterval(timer)轻松实现(如果已经清除,则不会发生任何事情)。

  • 有一组运行间隔。 像@jarvanJiang实现它的数组没有多大意义,因为如果只释放一个键就不想停止所有间隔(如while(timers.length) clearInterval(timers.pop()) )。 也没有清除最旧间隔的FIFO队列。

    相反,您需要每个键一个计时器ID - 运行间隔的映射。 释放按键后,您可以通过在地图中查找来确定要清除的间隔。

  • 实现更好的只是一个间隔, 游戏循环 ,以及指示当前按下哪些的布尔键的映射。 这将允许您管理干扰输入,并使动画运行更顺畅。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM