【问题标题】:Issue with intervals and click functions间隔和点击功能问题
【发布时间】:2018-05-31 11:39:34
【问题描述】:

我正在做一个项目,我们必须想出一个游戏,其中方块会根据math.random改变位置

我有两个问题

  1. 它似乎正在运行该函数的多个实例,因为在正方形重新定位的几个周期之后 - 它会变得疯狂并以看似随机的间隔在整个地方移动。

  2. 第二个问题是我第二次点击方形 div 时很难注册它。

到 JSFiddle 的链接:https://jsfiddle.net/ybpdjujb/

$(document).ready(function test() {
    $(document).on('click', '#target', function clicker() {
        $('#target').css('left', randPosX);
        $('#target').css('top', randPosY);
        clearInterval(fire)
        timeLeft = 2;
    });

    //Random
    var bodyWidth = $("#playArea").width();
    var bodyHeight = $("#playArea").height();
    var randPosX = Math.floor((Math.random() * bodyWidth / 1.1));
    var randPosY = Math.floor((Math.random() * bodyHeight / 1.1));

    //TIMER
    var timeLeft = 2;
    var elem = document.getElementById('time');
    var timerId = setInterval(countdown, 1000);

    function countdown() {
        if (timeLeft == 0) {
            doSomething();
            timeLeft = 5;
        } else {
            elem.innerHTML = timeLeft + ' seconds remaining';
            timeLeft--;
        }
    }

    function doSomething() {
        $('#target').css('left', randPosX);
        $('#target').css('top', randPosY);
        clearInterval(timerId);
    }

    var fire = setInterval(test, 2000);
});

【问题讨论】:

  • 这个游戏的目的是什么?继续改变方块的位置,当用户点击它时停止移动?
  • @raghav710 是的,很抱歉我解释得不够好。目标是在计时器用完之前按下方块,然后在新位置产生。 - 如果你设法点击方块,它将在一个新位置产生。随着计时器的重置。
  • 查看代码,即使您在给定时间内不按方块,它也会移动到新位置。我想了解点击和不点击之间的区别。有什么不同?
  • @raghav710 ,是的,我只是不擅长解释。在这里忍受我:目标是:你是否足够快地按下方块 - 你有 2 秒 - 如果时间用完,它会移动到一个新的位置。但如果你设法按下它,它也会移动到一个新的位置,但然后给你 1 分表示成功(我需要在这有意义之前实施某种评分)
  • 哦……现在明白了。谢谢你的解释。

标签: javascript jquery


【解决方案1】:

TL;DR:广场变得疯狂的原因是你在两个地方做了setInterval()。一个你做var fire = setInterval(test, 2000);,一个你做var timerId = setInterval(countdown, 1000);。删除其中一个(并修复一些其他问题),您的代码就会开始工作。

但是,我们不想就此止步,如果结构不正确,工作代码很快就会变得难以修改。因此,为了您和程序员社区的利益,让我们看看我们如何重构此代码。我相信这对未来的编码(和调试)练习很有用。如果这对您来说已经是常识,请考虑这是一个复习:)

第 1 步:仅将需要的内容放入 document.ready

这是一个简单的问题。文件准备好后你想做什么? 三件事

  1. 显示正方形
  2. 设置 onclick 处理程序
  3. 启动计时器

让我们只保留那些并将其余的移到document.ready 块之外。您正确地做的一件事是您认为应该放在一起的代码注释区域,让我们将它们转换为函数!在执行此操作时,我们注意到文件末尾的杂散setInterval() 可以删除。 您的代码现在应该如下所示(已完成的重构如下所述):

function doSomething() {
    positionSquareRandomly();
    clearInterval(timerId);
    timeLeft = 2;
    startTimer();
}

function positionSquareRandomly(){
    var bodyWidth = $("#playArea").width();
    var bodyHeight = $("#playArea").height();
    var randPosX = Math.floor((Math.random() * bodyWidth / 1.1));
    var randPosY = Math.floor((Math.random() * bodyHeight / 1.1));
    $('#target').css('left', randPosX);
    $('#target').css('top', randPosY);
}

function startTimer(){
    var timeLeft = 2;
    var elem = document.getElementById('time');
    var timerId = setInterval(countdown, 1000);
}

function countdown() {
    if (timeLeft == 0) {
        doSomething();
    } else {
        elem.innerHTML = timeLeft + ' seconds remaining';
        timeLeft--;
    }
}

function clicker() {
    doSomething();
}

$(document).ready(function test() {
    //Display square
    positionSquareRandomly();

    // Setup timer
    startTimer();

    // Setup click handler
    $(document).on('click', '#target', clicker);

});

第 2 步:重构 I

  1. positionSquareRandomly() 应该得到坐标并且显示正方形。因此,我们将 $('#target').css(..) 调用移至该方法
  2. 现在,当我们这样做时,clicker()doSomething() 看起来非常相似,所以 clicker() 现在调用 doSomething(),这反过来又定位正方形并重置计时器,即清除间隔,重置 timeLeft 并调用 @ 987654336@。
  3. clearInterval(fire) 因不需要而消失了。 timeLeft = 5 也不见了。

第 3 步:重构 II

很好,但现在我们看到什么都没有发生!按F12打开开发者控制台,点击控制台标签。我看到的错误是Uncaught ReferenceError: timeLeft is not defined。这是因为timeLeftstartTimer() 中声明,但我们也在尝试在countdown() 中使用它。我们通过在所有函数之上声明 timeLeft 来解决这个问题(使其成为全局)。

同样,将var elem 声明放在顶部。

在顶部声明var timerId = 0setInterval() 返回的 Id 始终非零,因此这是一个很好的初始值。 (Set timeout example)

就是这样!在倒计时的if 部分添加一些有用的elem.innerHTML,我们就会得到这个代码。

var timeLeft = 2;
var elem = document.getElementById('time');
var timerId = 0;

function doSomething() {
    positionSquareRandomly();
    clearInterval(timerId);
    timeLeft = 2;
    startTimer();
}

function positionSquareRandomly(){
    var bodyWidth = $("#playArea").width();
    var bodyHeight = $("#playArea").height();
    var randPosX = Math.floor((Math.random() * bodyWidth / 1.1));
    var randPosY = Math.floor((Math.random() * bodyHeight / 1.1));
    $('#target').css('left', randPosX);
    $('#target').css('top', randPosY);
}

function startTimer(){
    timerId = setInterval(countdown, 1000);
}

function countdown() {
    if (timeLeft == 0) {
        elem.innerHTML = '0 seconds remaining';
        doSomething();
    }
    else {
        elem.innerHTML = timeLeft + ' seconds remaining';
        timeLeft--;
    }
}

function clicker() {
    doSomething();
}

$(document).ready(function test() {
    //Display square
    positionSquareRandomly();

    // Setup timer
    startTimer();

        // Setup click handler
    $(document).on('click', '#target', clicker);

});

我们可以做更多的事情,但现在我相信代码清晰、简洁,最重要的是,可维护。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多