【问题标题】:What can I do so functions don't stack?我该怎么做才能使函数不堆叠?
【发布时间】:2023-04-04 21:16:01
【问题描述】:

所以这是一个倒数计时器,当我按下按钮时,倒计时从这条线开始:timePassed = timePassed += 1;

现在的问题是,如果我按下另一个按钮来重置计时器,那么这些功能就会开始相互叠加,并且秒数会变得更快。

我需要让所有按钮都能正常工作并重置经过的时间,这样它们就不会堆积...

const FULL_DASH_ARRAY = 283;
const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;

const COLOR_CODES = {
  info: {
    color: "green"
  },
  warning: {
    color: "orange",
    threshold: WARNING_THRESHOLD
  },
  alert: {
    color: "red",
    threshold: ALERT_THRESHOLD
  }
};

var TIME_LIMIT = 0;
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval = null;
let remainingPathColor = COLOR_CODES.info.color;



document.getElementById("app").innerHTML = `
<div class="base-timer">
  <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <g class="base-timer__circle">
      <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>
      <path
        id="base-timer-path-remaining"
        stroke-dasharray="283"
        class="base-timer__path-remaining ${remainingPathColor}"
        d="
          M 50, 50
          m -45, 0
          a 45,45 0 1,0 90,0
          a 45,45 0 1,0 -90,0
        "
      ></path>
    </g>
  </svg>
  <span id="base-timer-label" class="base-timer__label">${formatTime(
    timeLeft
  )}</span>
</div>
`;



function onTimesUp() {
  clearInterval(timerInterval);
}



function formatTime(time) {
  const minutes = Math.floor(time / 60);
  let seconds = time % 60;

  if (seconds < 10) {
    seconds = `0${seconds}`;
  }

  return `${minutes}:${seconds}`;
}

function setRemainingPathColor(timeLeft) {
  const { alert, warning, info } = COLOR_CODES;
  if (timeLeft <= alert.threshold) {
    document
      .getElementById("base-timer-path-remaining")
      .classList.remove(warning.color);
    document
      .getElementById("base-timer-path-remaining")
      .classList.add(alert.color);
  } else if (timeLeft <= warning.threshold) {
    document
      .getElementById("base-timer-path-remaining")
      .classList.remove(info.color);
    document
      .getElementById("base-timer-path-remaining")
      .classList.add(warning.color);
  }
}

function calculateTimeFraction() {
  const rawTimeFraction = timeLeft / TIME_LIMIT;
  return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);
}

function setCircleDasharray() {
  const circleDasharray = `${(
    calculateTimeFraction() * FULL_DASH_ARRAY
  ).toFixed(0)} 283`;
  document
    .getElementById("base-timer-path-remaining")
    .setAttribute("stroke-dasharray", circleDasharray);
}

function timer15(){
TIME_LIMIT = 901;
timePassed = 0;
timeLeft = TIME_LIMIT;
timerInterval = null;
remainingPathColor = COLOR_CODES.info.color;


  timerInterval = setInterval(() => {
    timePassed = timePassed += 0;
    timePassed = timePassed += 1;

    timeLeft = TIME_LIMIT - timePassed;
    document.getElementById("base-timer-label").innerHTML = formatTime(
      timeLeft
    );
    setCircleDasharray();
    setRemainingPathColor(timeLeft);

    if (timeLeft === 0) {
      onTimesUp();
    }
  }, 1000);
}


function timer30(){
  TIME_LIMIT = 1801;
  timePassed = 0;
  timeLeft = TIME_LIMIT;
  timerInterval = null;
  remainingPathColor = COLOR_CODES.info.color;
  timerInterval = setInterval(() => {
    timePassed = timePassed += 0;
    timePassed = timePassed += 1;
    timeLeft = TIME_LIMIT - timePassed;
    document.getElementById("base-timer-label").innerHTML = formatTime(
      timeLeft
    );
    setCircleDasharray();
    setRemainingPathColor(timeLeft);

    if (timeLeft === 0) {
      onTimesUp();
    }
  }, 1000);
  }

  function timer45(){
    TIME_LIMIT = 2701;
    timePassed = 0;
    timeLeft = TIME_LIMIT;
    timerInterval = null;
    remainingPathColor = COLOR_CODES.info.color;
    timerInterval = setInterval(() => {
      timePassed = timePassed += 1;
      timeLeft = TIME_LIMIT - timePassed;
      document.getElementById("base-timer-label").innerHTML = formatTime(
        timeLeft
      );
      setCircleDasharray();
      setRemainingPathColor(timeLeft);
  
      if (timeLeft === 0) {
        onTimesUp();
      }
    }, 1000);
    }

    function timer60(){
      TIME_LIMIT = 3601;
      timePassed = 0;
      timeLeft = TIME_LIMIT;
      timerInterval = null;
      remainingPathColor = COLOR_CODES.info.color;
      timerInterval = setInterval(() => {
        timePassed = timePassed += 1;
        timeLeft = TIME_LIMIT - timePassed;
        document.getElementById("base-timer-label").innerHTML = formatTime(
          timeLeft
        );
        setCircleDasharray();
        setRemainingPathColor(timeLeft);
    
        if (timeLeft === 0) {
          onTimesUp();
        }
      }, 1000);
      }
body {
    font-family: sans-serif;
    display: grid;
    height: 100vh;
    place-items: center;
  }
  
  .base-timer {
    position: relative;
    width: 300px;
    height: 300px;
  }
  
  .base-timer__svg {
    transform: scaleX(-1);
  }
  
  .base-timer__circle {
    fill: none;
    stroke: none;
  }
  
  .base-timer__path-elapsed {
    stroke-width: 7px;
    stroke: grey;
  }
  
  .base-timer__path-remaining {
    stroke-width: 7px;
    stroke-linecap: round;
    transform: rotate(90deg);
    transform-origin: center;
    transition: 1s linear all;
    fill-rule: nonzero;
    stroke: currentColor;
  }
  
  .base-timer__path-remaining.green {
    color: rgb(65, 184, 131);
  }
  
  .base-timer__path-remaining.orange {
    color: orange;
  }
  
  .base-timer__path-remaining.red {
    color: red;
  }
  
  .base-timer__label {
    position: absolute;
    width: 300px;
    height: 300px;
    top: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 48px;
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="timer.css">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <input type="button" onclick="timer15()" value="15 min">
    <input type="button" onclick="timer30()" value="30 min">
    <input type="button" onclick="timer45()" value="45 min">
    <input type="button" onclick="timer60()" value="60 min">

    <script src="timer.js"></script>
</body>
</html>

【问题讨论】:

  • 不确定你想用timePassed = timePassed += 0;做什么,这实际上不会修改timePassed的值,timePassed = timePassed += 1;最好写成timePassed += 1;
  • timePassed = timePassed += 0;只是我试图解决问题,我现在改变它,谢谢!

标签: javascript html function


【解决方案1】:

你需要一一清除区间,而不是只有一个变量来为它保留引用。

添加了清除间隔并在每次单击按钮时重置间隔以确保它们不会重叠的功能。

const FULL_DASH_ARRAY = 283;
const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;

const COLOR_CODES = {
  info: {
    color: "green"
  },
  warning: {
    color: "orange",
    threshold: WARNING_THRESHOLD
  },
  alert: {
    color: "red",
    threshold: ALERT_THRESHOLD
  }
};

var TIME_LIMIT = 0;
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval15 = null;
let timerInterval30 = null;
let timerInterval45 = null;
let timerInterval60 = null;
let remainingPathColor = COLOR_CODES.info.color;



document.getElementById("app").innerHTML = `
<div class="base-timer">
  <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <g class="base-timer__circle">
      <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>
      <path
        id="base-timer-path-remaining"
        stroke-dasharray="283"
        class="base-timer__path-remaining ${remainingPathColor}"
        d="
          M 50, 50
          m -45, 0
          a 45,45 0 1,0 90,0
          a 45,45 0 1,0 -90,0
        "
      ></path>
    </g>
  </svg>
  <span id="base-timer-label" class="base-timer__label">${formatTime(
    timeLeft
  )}</span>
</div>
`;

function clearIntervals(){
  clearInterval(timerInterval15);
  clearInterval(timerInterval30);
  clearInterval(timerInterval45);
  clearInterval(timerInterval60);
}

function onTimesUp() {
  clearIntervals();
}



function formatTime(time) {
  const minutes = Math.floor(time / 60);
  let seconds = time % 60;

  if (seconds < 10) {
    seconds = `0${seconds}`;
  }

  return `${minutes}:${seconds}`;
}

function setRemainingPathColor(timeLeft) {
  const { alert, warning, info } = COLOR_CODES;
  if (timeLeft <= alert.threshold) {
    document
      .getElementById("base-timer-path-remaining")
      .classList.remove(warning.color);
    document
      .getElementById("base-timer-path-remaining")
      .classList.add(alert.color);
  } else if (timeLeft <= warning.threshold) {
    document
      .getElementById("base-timer-path-remaining")
      .classList.remove(info.color);
    document
      .getElementById("base-timer-path-remaining")
      .classList.add(warning.color);
  }
}

function calculateTimeFraction() {
  const rawTimeFraction = timeLeft / TIME_LIMIT;
  return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);
}

function setCircleDasharray() {
  const circleDasharray = `${(
    calculateTimeFraction() * FULL_DASH_ARRAY
  ).toFixed(0)} 283`;
  document
    .getElementById("base-timer-path-remaining")
    .setAttribute("stroke-dasharray", circleDasharray);
}

function timer15(){
TIME_LIMIT = 901;
timePassed = 0;
timeLeft = TIME_LIMIT;
clearIntervals();
remainingPathColor = COLOR_CODES.info.color;


  timerInterval15 = setInterval(() => {
    timePassed = timePassed += 0;
    timePassed = timePassed += 1;

    timeLeft = TIME_LIMIT - timePassed;
    document.getElementById("base-timer-label").innerHTML = formatTime(
      timeLeft
    );
    setCircleDasharray();
    setRemainingPathColor(timeLeft);

    if (timeLeft === 0) {
      onTimesUp();
    }
  }, 1000);
}


function timer30(){
  TIME_LIMIT = 1801;
  timePassed = 0;
  timeLeft = TIME_LIMIT;
  clearIntervals();
  remainingPathColor = COLOR_CODES.info.color;
  timerInterval30 = setInterval(() => {
    timePassed = timePassed += 0;
    timePassed = timePassed += 1;
    timeLeft = TIME_LIMIT - timePassed;
    document.getElementById("base-timer-label").innerHTML = formatTime(
      timeLeft
    );
    setCircleDasharray();
    setRemainingPathColor(timeLeft);

    if (timeLeft === 0) {
      onTimesUp();
    }
  }, 1000);
  }

  function timer45(){
    TIME_LIMIT = 2701;
    timePassed = 0;
    timeLeft = TIME_LIMIT;
    clearIntervals();
    remainingPathColor = COLOR_CODES.info.color;
    timerInterval45 = setInterval(() => {
      timePassed = timePassed += 1;
      timeLeft = TIME_LIMIT - timePassed;
      document.getElementById("base-timer-label").innerHTML = formatTime(
        timeLeft
      );
      setCircleDasharray();
      setRemainingPathColor(timeLeft);
  
      if (timeLeft === 0) {
        onTimesUp();
      }
    }, 1000);
    }

    function timer60(){
      TIME_LIMIT = 3601;
      timePassed = 0;
      timeLeft = TIME_LIMIT;
      clearIntervals();
      remainingPathColor = COLOR_CODES.info.color;
      timerInterval60 = setInterval(() => {
        timePassed = timePassed += 1;
        timeLeft = TIME_LIMIT - timePassed;
        document.getElementById("base-timer-label").innerHTML = formatTime(
          timeLeft
        );
        setCircleDasharray();
        setRemainingPathColor(timeLeft);
    
        if (timeLeft === 0) {
          onTimesUp();
        }
      }, 1000);
      }
body {
    font-family: sans-serif;
    display: grid;
    height: 100vh;
    place-items: center;
  }
  
  .base-timer {
    position: relative;
    width: 300px;
    height: 300px;
  }
  
  .base-timer__svg {
    transform: scaleX(-1);
  }
  
  .base-timer__circle {
    fill: none;
    stroke: none;
  }
  
  .base-timer__path-elapsed {
    stroke-width: 7px;
    stroke: grey;
  }
  
  .base-timer__path-remaining {
    stroke-width: 7px;
    stroke-linecap: round;
    transform: rotate(90deg);
    transform-origin: center;
    transition: 1s linear all;
    fill-rule: nonzero;
    stroke: currentColor;
  }
  
  .base-timer__path-remaining.green {
    color: rgb(65, 184, 131);
  }
  
  .base-timer__path-remaining.orange {
    color: orange;
  }
  
  .base-timer__path-remaining.red {
    color: red;
  }
  
  .base-timer__label {
    position: absolute;
    width: 300px;
    height: 300px;
    top: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 48px;
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="timer.css">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <input type="button" onclick="timer15()" value="15 min">
    <input type="button" onclick="timer30()" value="30 min">
    <input type="button" onclick="timer45()" value="45 min">
    <input type="button" onclick="timer60()" value="60 min">

    <script src="timer.js"></script>
</body>
</html>

【讨论】:

  • 如果有帮助,您可以将答案标记为已接受:)
【解决方案2】:

在每个计时器函数中,您都设置了timerInterval = null。这不会停止或清除先前注册的间隔,而只会从timerInterval 变量中删除它的引用。所以在设置新的时间间隔之前,你必须先清除间隔。

例如在你的 timer30 timer45 timer60 函数中。在setInterval之前先清除timerInterval

...
clearInterval(timerInterval);

timerInterval = setInterval(() => { ... }, 1000)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    相关资源
    最近更新 更多