如果多次单击 setInterval() 按钮,则不会触发 clearInterval()

clearInterval() won't be triggered if setInterval() button is clicked multiple times

我正在玩一个颜色生成器应用程序,我添加了一个“迪斯科”功能,它会触发随机颜色以随着歌曲的节奏“闪烁”。顺便说一下,您将听不到它,但它是“拒绝什么”:))

一切正常,但是:如果我多次点击“Disco”按钮,setInterval()会加速(我不介意,事实上我喜欢),但不会被清除一旦我决定通过在移动设备上滚动或滑动来停止它,就再也没有了。

我在这里阅读了多个类似的问题,但是none遇到了类似的问题,我真的不知道我能做什么。

我想让它在多次点击时加速,但我也希望能够清除它。

let button = document.querySelector('.button')
let body = document.querySelector('.body')
let container = document.querySelector('.container')
let disco = document.querySelector('.disco')
let song = document.querySelector('.song')

button.addEventListener('click', ()=> {
  let colorOne = parseInt((Math.random() * 255) + 1)
  let colorTwo = parseInt((Math.random() * 255) + 1)
  let colorThree = parseInt((Math.random() * 255) + 1)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'

  document.querySelector('.color').innerText = 'rgb (' + colorOne + ', ' + colorTwo + ', ' + colorThree
+ ')'

  button.style.border = 'none'
  document.querySelector('.scrollto').style.display = 'block'

  disco.style.display = 'none'
})

let dance = function() {
  let colorOne = parseInt((Math.random() * 255) + 1)
  let colorTwo = parseInt((Math.random() * 255) + 1)
  let colorThree = parseInt((Math.random() * 255) + 1)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'
  }

let dancing;
let stopping;

disco.addEventListener('click', ()=> {
  document.querySelector('.scrollto').style.display = 'block'
  dancing = setInterval(dance,300)

  stopping = setTimeout(function() {
    clearInterval(dancing)
    button.style.display = 'block'
    body.style.background = 'white'
    document.querySelector('.scrollto').style.display = 'none'
   }, 15400)

  if(song.paused) {
    song.play()
    button.style.display = 'none'
  }
})


window.addEventListener('touchmove', ()=> {
  body.style.background = 'white'
  document.querySelector('.color').innerText = ''
  document.querySelector('.scrollto').style.display = 'none'
  button.style.border = '1px solid black'

  clearInterval(dancing)
  clearTimeout(stopping)
  song.pause()
  song.currentTime = 0
  button.style.display = 'block'
  disco.style.display = 'block'
})
.button {
  font-family: 'Poppins', sans-serif;
  border-radius: .5em;
  padding: .3em .7em;
  font-size: 1.1em;
  position: relative;
  background: white;
  mix-blend-mode: screen;
  border: 1px solid black;
}

.color {
  font-family: 'Poppins', sans-serif;
  color: white;
  text-shadow: 1px 1px 3px black;
  letter-spacing: 1px;
}

.container {
  text-align: center;
  position: absolute;
  top: 40vh;
  left: 50vw;
  transform: translate(-50%, -50%);
}

.scrollto {
  position: absolute;
  bottom: 10px;
  left: 50vw;
  transform: translateX(-50%);
  font-family: 'Poppins', sans-serif;
  font-size: .7em;
  display: none;
}

.disco {
  position: absolute;
  bottom: 5px;
  right: 10px;
  font-family: 'Poppins', sans-serif;
  font-size: .8em;
  border: .5px solid black;
  border-radius: .3em;
  padding: 0 .3em;
  padding-top: .1em;
}
<body class="body">
  
  <div class="container">
    <h3 class="button">Generate Colour</h3>
    <p class="color"></p>
  </div>

  <div class="line">
    <p class="scrollto">swipe on screen to reset</p>
  </div>

  <h3 class="disco">Disco</h3>
  <audio class="song" src="song.mp3"></audio>

这是因为你每次点击都改变了dancing变量的内容。这意味着在单击 1 时它将引用 setInterval1,在单击 2 时引用 setInterval2 等。然后当您尝试执行 clearInterval 时,您实际上只清除了您创建的最后一个引用。

您可以通过在添加新间隔之前简单地清除旧间隔来避免它:

(我将停止事件更改为右键单击,例如目的)

let button = document.querySelector('.button')
let body = document.querySelector('.body')
let container = document.querySelector('.container')
let disco = document.querySelector('.disco')
let song = document.querySelector('.song')

button.addEventListener('click', ()=> {
  let colorOne = parseInt((Math.random() * 255) + 1)
  let colorTwo = parseInt((Math.random() * 255) + 1)
  let colorThree = parseInt((Math.random() * 255) + 1)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'

  document.querySelector('.color').innerText = 'rgb (' + colorOne + ', ' + colorTwo + ', ' + colorThree
+ ')'

  button.style.border = 'none'
  document.querySelector('.scrollto').style.display = 'block'

  disco.style.display = 'none'
})

let dance = function() {
  let colorOne = parseInt((Math.random() * 255) + 1)
  let colorTwo = parseInt((Math.random() * 255) + 1)
  let colorThree = parseInt((Math.random() * 255) + 1)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'
  }

let dancing;
let stopping;

disco.addEventListener('click', ()=> {
  document.querySelector('.scrollto').style.display = 'block'
  clearInterval(dancing);
  clearTimeout(stopping)
  dancing = setInterval(dance,300)

  stopping = setTimeout(function() {
    clearInterval(dancing)
    button.style.display = 'block'
    body.style.background = 'white'
    document.querySelector('.scrollto').style.display = 'none'
   }, 15400)

  if(song.paused) {
    //song.play()
    button.style.display = 'none'
  }
})


window.addEventListener('contextmenu', ()=> {
  body.style.background = 'white'
  document.querySelector('.color').innerText = ''
  document.querySelector('.scrollto').style.display = 'none'
  button.style.border = '1px solid black'

  clearInterval(dancing)
  clearTimeout(stopping)
  song.pause()
  song.currentTime = 0
  button.style.display = 'block'
  disco.style.display = 'block'
})
.button {
  font-family: 'Poppins', sans-serif;
  border-radius: .5em;
  padding: .3em .7em;
  font-size: 1.1em;
  position: relative;
  background: white;
  mix-blend-mode: screen;
  border: 1px solid black;
}

.color {
  font-family: 'Poppins', sans-serif;
  color: white;
  text-shadow: 1px 1px 3px black;
  letter-spacing: 1px;
}

.container {
  text-align: center;
  position: absolute;
  top: 40vh;
  left: 50vw;
  transform: translate(-50%, -50%);
}

.scrollto {
  position: absolute;
  bottom: 10px;
  left: 50vw;
  transform: translateX(-50%);
  font-family: 'Poppins', sans-serif;
  font-size: .7em;
  display: none;
}

.disco {
  position: absolute;
  bottom: 5px;
  right: 10px;
  font-family: 'Poppins', sans-serif;
  font-size: .8em;
  border: .5px solid black;
  border-radius: .3em;
  padding: 0 .3em;
  padding-top: .1em;
}
<body class="body">
  
  <div class="container">
    <h3 class="button">Generate Colour</h3>
    <p class="color"></p>
  </div>

  <div class="line">
    <p class="scrollto">swipe on screen to reset</p>
  </div>

  <h3 class="disco">Disco</h3>
  <audio class="song" src="song.mp3"></audio>

编辑:

从评论中看出你想保留加速效果:

let button = document.querySelector('.button')
let body = document.querySelector('.body')
let container = document.querySelector('.container')
let disco = document.querySelector('.disco')
let song = document.querySelector('.song')

button.addEventListener('click', ()=> {
  let colorOne = parseInt((Math.random() * 255) + 1)
  let colorTwo = parseInt((Math.random() * 255) + 1)
  let colorThree = parseInt((Math.random() * 255) + 1)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'

  document.querySelector('.color').innerText = 'rgb (' + colorOne + ', ' + colorTwo + ', ' + colorThree
+ ')'

  button.style.border = 'none'
  document.querySelector('.scrollto').style.display = 'block'

  disco.style.display = 'none'
})

let dance = function() {
  let colorOne = parseInt((Math.random() * 255) + 1)
  let colorTwo = parseInt((Math.random() * 255) + 1)
  let colorThree = parseInt((Math.random() * 255) + 1)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'
  }

let dancing;
let stopping;
let speed = 300;
const accFactor = 1.5;

disco.addEventListener('click', ()=> {
  document.querySelector('.scrollto').style.display = 'block'
  if(dancing) {
   clearInterval(dancing);
   clearTimeout(stopping);
    speed = speed/accFactor;
  }
  dancing = setInterval(dance,speed);

  stopping = setTimeout(function() {
    clearInterval(dancing)
    button.style.display = 'block'
    body.style.background = 'white'
    document.querySelector('.scrollto').style.display = 'none'
   }, 15400)

  if(song.paused) {
    //song.play()
    button.style.display = 'none'
  }
})


window.addEventListener('contextmenu', ()=> {
  body.style.background = 'white'
  document.querySelector('.color').innerText = ''
  document.querySelector('.scrollto').style.display = 'none'
  button.style.border = '1px solid black'

  clearInterval(dancing)
  clearTimeout(stopping)
  song.pause()
  song.currentTime = 0
  button.style.display = 'block'
  disco.style.display = 'block'
})
.button {
  font-family: 'Poppins', sans-serif;
  border-radius: .5em;
  padding: .3em .7em;
  font-size: 1.1em;
  position: relative;
  background: white;
  mix-blend-mode: screen;
  border: 1px solid black;
}

.color {
  font-family: 'Poppins', sans-serif;
  color: white;
  text-shadow: 1px 1px 3px black;
  letter-spacing: 1px;
}

.container {
  text-align: center;
  position: absolute;
  top: 40vh;
  left: 50vw;
  transform: translate(-50%, -50%);
}

.scrollto {
  position: absolute;
  bottom: 10px;
  left: 50vw;
  transform: translateX(-50%);
  font-family: 'Poppins', sans-serif;
  font-size: .7em;
  display: none;
}

.disco {
  position: absolute;
  bottom: 5px;
  right: 10px;
  font-family: 'Poppins', sans-serif;
  font-size: .8em;
  border: .5px solid black;
  border-radius: .3em;
  padding: 0 .3em;
  padding-top: .1em;
}
<body class="body">
  
  <div class="container">
    <h3 class="button">Generate Colour</h3>
    <p class="color"></p>
  </div>

  <div class="line">
    <p class="scrollto">swipe on screen to reset</p>
  </div>

  <h3 class="disco">Disco</h3>
  <audio class="song" src="song.mp3"></audio>