JavaScript - setInterval 函数:间隔不会清除

JavaScript - setInterval function: interval won't clear

注意:我查看了所有与 setInterval / clearInterval 相关的问题和答案,其中 none 有任何帮助。不要将其标记为重复项。

我有一个 HTML 页面,其中的一个元素的背景颜色会发生变化(从红色到绿色再到蓝色等等)。单击时,颜色应停止变化。我正在使用 setInterval 来 运行 一个 updateCard() 函数,该函数应该检查颜色当前是否正在更改并清除间隔或重置它。单击时,它不会停止更改颜色。我添加了 console.log 检查以查看间隔 ID 是否正在更改,我发现它是(我的函数称为更新)所以我修复了它。间隔 ID 现在在清除时与定义时相同。这是我的 colorChange.js 文件,它嵌入在我的 HTML.

var titleCard = document.getElementById("titleCard"),
 red = 255,
 green = 255,
 blue = 255,
 redDir = 1,
 greenDir = -1,
 blueDir = -1,
 on = true,
 colorChange = setInterval(updateCard, 10);

function updateCard() {
 if (red > 255) red = 255;
 if (green > 255) green = 255;
 if (blue > 255) blue = 255;
 if (red < 0) red = 0;
 if (green < 0) green = 0;
 if (blue < 0) blue = 0;
 
 red += redDir;
 green += greenDir;
 blue += blueDir;
 
 if (red >= 255 && green <= 0 && blue <= 0) turnGreen();
 if (red <= 0 && green >= 255 && blue <= 0) turnBlue();
 if (red <= 0 && green <= 0 && blue >= 255) turnRed();
 
 titleCard.style.backgroundColor = "rgb(" + red + "," +  green + "," + blue + ")";
}

function turnRed() {
 redDir = 1;
 greenDir = -1;
 blueDir = -1;
}

function turnGreen() {
 redDir = -1;
 greenDir = 1;
 blueDir = -1;
}

function turnBlue() {
 redDir = -1;
 greenDir = -1;
 blueDir = 1;
}

titleCard.onclick = function() {
 if (on) {
  console.log("Clearing: " + colorChange);
  clearInterval(colorChange);
  on = false;
 } else {
  colorChange = setInterval(updateCard, 10);
  console.log("Set: " + colorChange);
  on = true;
 }
}
<!DOCTYPE HTML>
<html>
 <head>
  <title>My Website</title>
  <link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico"/>
  <link rel="apple-touch-icon" href="images/apple_icon.png"/>
  <link rel="apple-touch-icon-precomposed" href="images/apple_icon.png"/>
  <link rel="stylesheet" href="/css/materialize.min.css"/>
  <link rel="stylesheet" href="/css/style.css"/>
  
 </head>
 <body>
  <div class="container">
   <div class="card hoverable">
    <h1 id="titleCard" class="card-content center">My Name</h1>
   </div>
  </div>
  <div class="row">
   <div class="col s4 push-s4">
    <div id="welcomeCard" class="card teal lighten-3">
     <p class="card-content center">Welcome to my website.<br/>Enjoy your stay.</p>
    </div>
   </div>
  </div>
  <div id="background1"></div>
 </body>
 <script src="/js/colorChange.js"></script>
 <script src="/js/changeTitle.js"></script>
 <script src="/js/style.js"></script>
</html>

这是我控制台中元素被点击 5 次的示例:

colorChange.js:50 Clearing: 61
colorChange.js:55 Set: 62
colorChange.js:50 Clearing: 62
colorChange.js:55 Set: 63
colorChange.js:50 Clearing: 63

这证明 clearInterval 调用正在清除正确的 ID。为什么颜色还在变?

编辑: 好笑的是,上面的代码片段实际上运行正常。然而,在我的网页中,它没有。我比以前更糊涂了。

编辑 2:我添加了完整的 HTML 页面。

编辑 3: 这是我的其他 JS 文件,可能那里有问题?

changeTitle.js

var titleCard = document.getElementById("titleCard");
 currentTime = new Date().getHours() + ":" + new Date().getMinutes(),
 today = new Date().getMonth() + 1 + "/" + new Date().getDate(),
 colorChange = setInterval(updateCard, 10);

function updateCard() {
 currentTime = new Date().getHours() + ":" + new Date().getMinutes();
 if (currentTime == "11:11" || currentTime == "23:11") changeTitle("Make a wish!", 1);
 else if (today == "2/13") changeTitle("Happy birthday to me", 1);
 else if (today == "12/11") changeTitle("Happy birthday, Kayla!", 1);
 else if (today == "3/7") changeTitle("Happy birthday, Nathan!", 1);
 else if (today == "1/1") changeTitle("Happy birthday, Mom!", 1);
 else if (today == "1/29") changeTitle("Happy birthday, Dad!", 1);
 else if (today == "8/3") changeTitle("Happy birthday, Brandon!", 1);
 else if (today == "7/24") changeTitle("Happy birthday, Dustin!", 1);
 else if (today == "11/23") changeTitle("Happy birthday, Branson!", 1);
 else if (today == "11/8") changeTitle("Happy birthday, Jack!", 1);
 else defaultTitle();
}

function changeTitle(body, interval) {
 titleCard.innerHTML = body;
 clearInterval(colorChange);
 colorChange = setInterval(updateCard, interval);
}

function defaultTitle() {
 titleCard.innerHTML = "MY NAME";
 clearInterval(colorChange);
 colorChange = setInterval(updateCard, 10);
}

style.js

var background1 = document.getElementById("background1");
background1.style.position = "absolute";
background1.style.backgroundColor = "black";
background1.style.top = 0;
background1.style.left = 0;
background1.style.width = "100%";
background1.style.height = "25%";
background1.style.zIndex = -1;

我快要死了

最终编辑:已解决,查看@GregL 和@CodeiSir 的答案。

我完成了代码,

这是一个有效的例子:(按 运行)(如果你想知道,当鼠标按钮在它按下的同一个对象上上升时,onclick 被触发,所以你可能没有即时反应,使用 onmousedown 来查看即时反应)

var titleCard = document.getElementById("titleCard"),
  red = 255,
  green = 255,
  blue = 255,
  redDir = 1,
  greenDir = -1,
  blueDir = -1,
  on = true,
  colorChange = setInterval(updateCard, 10);

function updateCard() {
  if (red > 255) red = 255;
  if (green > 255) green = 255;
  if (blue > 255) blue = 255;
  if (red < 0) red = 0;
  if (green < 0) green = 0;
  if (blue < 0) blue = 0;

  red += redDir;
  green += greenDir;
  blue += blueDir;

  if (red >= 255 && green <= 0 && blue <= 0) turnGreen();
  if (red <= 0 && green >= 255 && blue <= 0) turnBlue();
  if (red <= 0 && green <= 0 && blue >= 255) turnRed();

  titleCard.style.backgroundColor = "rgb(" + red + "," + green + "," + blue + ")";
}

function turnRed() {
  redDir = 1;
  greenDir = -1;
  blueDir = -1;
}

function turnGreen() {
  redDir = -1;
  greenDir = 1;
  blueDir = -1;
}

function turnBlue() {
  redDir = -1;
  greenDir = -1;
  blueDir = 1;
}

titleCard.onclick = function() {
  if (on) {
    console.log("Clearing: " + colorChange);
    clearInterval(colorChange);
    on = false;
  } else {
    colorChange = setInterval(updateCard, 10);
    console.log("Set: " + colorChange);
    on = true;
  }
}
<div id="titleCard" style="height: 100px; width: 100px"></div>

编辑: 这是问题所在: 您再次在 changeTitle.js 中使用相同的变量:

var titleCard = document.getElementById("titleCard");
    currentTime = new Date().getHours() + ":" + new Date().getMinutes(),
    today = new Date().getMonth() + 1 + "/" + new Date().getDate(),
    colorChange = setInterval(updateCard, 10);

您将不得不为您的每个文件使用不同的变量

问题是你在多个JS文件中重新定义了一些关键变量和函数,所以后面的值会覆盖前面的值,导致原来的值变成"lost".

这是因为在 Javascript 中,只有函数会创建一个新的作用域,因此任何 JS 文件中函数之外的内容都将位于全局命名空间中。

但是,您可以使用一种称为 IIFE(通常发音为 "iffy")的技术来利用函数创建新命名范围的事实,从而将每个代码文件彼此隔离,并允许一切正常工作。

这里有一个 forked Plunkr 可以正常工作。

核心更改是将此行添加到两个 JS 文件的顶部:

(function () {

每个 JS 文件底部的这一行:

})();

编辑:归功于@CodeiSir,他发现问题是两个 JS 文件中变量和函数名称的重用。