暂停与时钟恢复JavaScript计时器

发布于 2025-01-22 21:57:49 字数 2076 浏览 0 评论 0原文

我创建了一个应用程序,用户可以输入时间,计时器和时钟手将一致倒计时。

但是,当我停下来恢复时,计时器UI按预期工作,但时钟可以回到其静止位置,而不是继续从暂停的位置继续进行。

用户应该能够随时输入,并且时钟手应该反映输入的时间与剩余时间之间的差异 - 如进度栏,从100%到0%。

如何在时钟修复此暂停 +简历行为?

小提琴

let remaining = duration
let timer = null
let end = 0

// Start button
startButton.addEventListener('click', e => {
  // Continue if timer is running
  if (timer) return

  duration = (hoursEntered * 3600000) + (minutesEntered * 60000) + (secondsEntered * 1000);
  remaining = duration

  // Get end timestamp based on current time + remaining time
  end = Date.now() + remaining

  // Render the remaining time every 16ms (approx 60fps)
  timer = setInterval(() => {
    // If remainisng time is zero, stop clock
    if (end - Date.now() <= 16) {
      clearInterval(timer);
      timer = 0;
      showStartButton()
    } else {
      render(end - Date.now())
      animateRing();
    }
  }, 16)
})

// Pause button
pauseButton.addEventListener('click', e => {
  // Do nothing if timer not running
  if(!timer) return
  
  // Otherwise, clear timer
  clearInterval(timer)
  timer = null
  
  // Note the remaining time
  remaining = end - Date.now()
  render(remaining)
})

// Divide time left by time remaining
const calcPercent = () => {
  return percent = (end - Date.now()) / remaining;
};

// Update the ring and clockhand as time passes, starting with 283
// Where the length of arc = 2πr = 2 * π * 45 = 282.6
const animateRing = () => {
  const ringArray = `${(calcPercent() * ring).toFixed(0)} 283`;
  document.getElementById('base-timer-path-remaining').setAttribute('stroke-dasharray', ringArray);
  // Animate clockhand
  document.getElementById('clockhand').style.transform = 'rotate(-' + (calcPercent() * 360) + 'deg)';
};

render(remaining)

I created an app where users can input time, and a timer and clockhand will countdown in unison.

When I pause then resume, however, the timer UI works as anticipated, but the clock resets back to its resting position instead of continuing from its paused position.

The user should be able to input any time, and the clockhand should reflect the difference between the time entered and the time remaining--actinig like a progress bar, running from 100% to 0%.

enter image description here

How can I fix this pause + resume behavior in the clock?

The Fiddle

JavaScript MVP

let remaining = duration
let timer = null
let end = 0

// Start button
startButton.addEventListener('click', e => {
  // Continue if timer is running
  if (timer) return

  duration = (hoursEntered * 3600000) + (minutesEntered * 60000) + (secondsEntered * 1000);
  remaining = duration

  // Get end timestamp based on current time + remaining time
  end = Date.now() + remaining

  // Render the remaining time every 16ms (approx 60fps)
  timer = setInterval(() => {
    // If remainisng time is zero, stop clock
    if (end - Date.now() <= 16) {
      clearInterval(timer);
      timer = 0;
      showStartButton()
    } else {
      render(end - Date.now())
      animateRing();
    }
  }, 16)
})

// Pause button
pauseButton.addEventListener('click', e => {
  // Do nothing if timer not running
  if(!timer) return
  
  // Otherwise, clear timer
  clearInterval(timer)
  timer = null
  
  // Note the remaining time
  remaining = end - Date.now()
  render(remaining)
})

// Divide time left by time remaining
const calcPercent = () => {
  return percent = (end - Date.now()) / remaining;
};

// Update the ring and clockhand as time passes, starting with 283
// Where the length of arc = 2πr = 2 * π * 45 = 282.6
const animateRing = () => {
  const ringArray = `${(calcPercent() * ring).toFixed(0)} 283`;
  document.getElementById('base-timer-path-remaining').setAttribute('stroke-dasharray', ringArray);
  // Animate clockhand
  document.getElementById('clockhand').style.transform = 'rotate(-' + (calcPercent() * 360) + 'deg)';
};

render(remaining)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

歌枕肩 2025-01-29 21:57:49

按下“开始”按钮时,Calccent总是1。您将剩余时间除以剩余时间(end = date.now() +剩余时间与end -date.now()=剩余时间相同。我建议重写算法中有几种等效的表达式。但是,下面的代码正常运行您想要的方式,我在小提琴中进行了测试。

// Get inputs and buttons
const hoursInput = document.getElementById('hours')
const minutesInput = document.getElementById('minutes')
const secondsInput = document.getElementById('seconds')
const startButton = document.getElementById('start')
const pauseButton = document.getElementById('pause')
const resetButton = document.getElementById('reset')
var startSeconds=900000;
// Leading zeroes for timer UI
const pad = v => `00${v}`.slice(-2)

// Compute units from milliseconds
const hours = m => Math.floor((m / 3600000) % 24)
const minutes = m => Math.floor((m / 60000) % 60)
const seconds = m => Math.floor((m / 1000) % 60)

// Render function
const render = v => {
  hoursInput.value = pad(hours(v))
  minutesInput.value = pad(minutes(v))
  secondsInput.value = pad(seconds(v))
  
  const hoursEntered = document.getElementById('hours').value;
  const minutesEntered = document.getElementById('minutes').value;
  const secondsEntered = document.getElementById('seconds').value;

  duration = (hoursEntered * 3600000) + (minutesEntered * 60000) + (secondsEntered * 1000);
  remaining = duration
}

// Length of arc
const ring = 283;

// Set initial value to 15 minutes
let duration = 900000

let remaining = duration
let timer = null
let end = 0

// Start button
startButton.addEventListener('click', e => {
  // Continue if timer is running
  if (timer) return

  // Show/hide start and pause
  showPauseButton()

  // Convert user input to milliseconds
  const hoursEntered = document.getElementById('hours').value;
  const minutesEntered = document.getElementById('minutes').value;
  const secondsEntered = document.getElementById('seconds').value;

  duration = (hoursEntered * 3600000) + (minutesEntered * 60000) + (secondsEntered * 1000);
  remaining = duration

  // Get end timestamp based on current time + remaining time
  end = Date.now() + remaining

  // Render the remaining time every 16ms (approx 60fps)
  timer = setInterval(() => {
    // If remainisng time is zero, stop clock
    if (end - Date.now() <= 16) {
      clearInterval(timer);
      timer = 0;
      showStartButton()
    } else {
      render(end - Date.now())
      animateRing();
    }
  }, 16)
})

// Pause button
pauseButton.addEventListener('click', e => {
  // Do nothing if timer not running
  if(!timer) return
  
  // Otherwise, clear timer
  clearInterval(timer)
  timer = null

  // Show/hide start and pause
  showStartButton()
  
  // Note the remaining time
  remaining = end - Date.now()
  render(remaining)
})

// Reset button
resetButton.addEventListener('click', e => {
  // Show/hide start and pause
  showStartButton()
  
  // Clear timer
  clearInterval(timer)
  timer = null

  // Reset ring
  document.getElementById('base-timer-path-remaining').setAttribute('stroke-dasharray', '283 283');
  document.getElementById('clockhand').style.transform = 'rotate(-360deg)';

  // Reset remaining to original duration
  remaining = 900000
  render(remaining)
})

// Show pause button, hide start button
const showPauseButton = () => {
  document.getElementById('pause').style.display = 'flex';
  document.getElementById('start').style.display = 'none';
};

// Show start button, hide pause button
const showStartButton = () => {
  document.getElementById('pause').style.display = 'none';   
  document.getElementById('start').style.display = 'flex';
};

// Divide time left by time remaining
const calcPercent = () => {
  return percent = remaining/startSeconds;
};

// Update the ring and clockhand as time passes, starting with 283
// Where the length of arc = 2πr = 2 * π * 45 = 282.6
const animateRing = () => {
  const ringArray = `${(calcPercent() * ring).toFixed(0)} 283`;
  document.getElementById('base-timer-path-remaining').setAttribute('stroke-dasharray', ringArray);
  // Animate clockhand
  document.getElementById('clockhand').style.transform = 'rotate(-' + (calcPercent() * 360) + 'deg)';
};

render(remaining)

calcPercent was always 1 when you hit the start button. You were dividing the remaining time by the remaining time (end = Date.now() + remaining is the same as end - Date.now() = remaining). You have several equivalent expressions in your algorithm, I suggest a rewrite. However, the code below is functioning the way you want, I tested in your fiddle.

// Get inputs and buttons
const hoursInput = document.getElementById('hours')
const minutesInput = document.getElementById('minutes')
const secondsInput = document.getElementById('seconds')
const startButton = document.getElementById('start')
const pauseButton = document.getElementById('pause')
const resetButton = document.getElementById('reset')
var startSeconds=900000;
// Leading zeroes for timer UI
const pad = v => `00${v}`.slice(-2)

// Compute units from milliseconds
const hours = m => Math.floor((m / 3600000) % 24)
const minutes = m => Math.floor((m / 60000) % 60)
const seconds = m => Math.floor((m / 1000) % 60)

// Render function
const render = v => {
  hoursInput.value = pad(hours(v))
  minutesInput.value = pad(minutes(v))
  secondsInput.value = pad(seconds(v))
  
  const hoursEntered = document.getElementById('hours').value;
  const minutesEntered = document.getElementById('minutes').value;
  const secondsEntered = document.getElementById('seconds').value;

  duration = (hoursEntered * 3600000) + (minutesEntered * 60000) + (secondsEntered * 1000);
  remaining = duration
}

// Length of arc
const ring = 283;

// Set initial value to 15 minutes
let duration = 900000

let remaining = duration
let timer = null
let end = 0

// Start button
startButton.addEventListener('click', e => {
  // Continue if timer is running
  if (timer) return

  // Show/hide start and pause
  showPauseButton()

  // Convert user input to milliseconds
  const hoursEntered = document.getElementById('hours').value;
  const minutesEntered = document.getElementById('minutes').value;
  const secondsEntered = document.getElementById('seconds').value;

  duration = (hoursEntered * 3600000) + (minutesEntered * 60000) + (secondsEntered * 1000);
  remaining = duration

  // Get end timestamp based on current time + remaining time
  end = Date.now() + remaining

  // Render the remaining time every 16ms (approx 60fps)
  timer = setInterval(() => {
    // If remainisng time is zero, stop clock
    if (end - Date.now() <= 16) {
      clearInterval(timer);
      timer = 0;
      showStartButton()
    } else {
      render(end - Date.now())
      animateRing();
    }
  }, 16)
})

// Pause button
pauseButton.addEventListener('click', e => {
  // Do nothing if timer not running
  if(!timer) return
  
  // Otherwise, clear timer
  clearInterval(timer)
  timer = null

  // Show/hide start and pause
  showStartButton()
  
  // Note the remaining time
  remaining = end - Date.now()
  render(remaining)
})

// Reset button
resetButton.addEventListener('click', e => {
  // Show/hide start and pause
  showStartButton()
  
  // Clear timer
  clearInterval(timer)
  timer = null

  // Reset ring
  document.getElementById('base-timer-path-remaining').setAttribute('stroke-dasharray', '283 283');
  document.getElementById('clockhand').style.transform = 'rotate(-360deg)';

  // Reset remaining to original duration
  remaining = 900000
  render(remaining)
})

// Show pause button, hide start button
const showPauseButton = () => {
  document.getElementById('pause').style.display = 'flex';
  document.getElementById('start').style.display = 'none';
};

// Show start button, hide pause button
const showStartButton = () => {
  document.getElementById('pause').style.display = 'none';   
  document.getElementById('start').style.display = 'flex';
};

// Divide time left by time remaining
const calcPercent = () => {
  return percent = remaining/startSeconds;
};

// Update the ring and clockhand as time passes, starting with 283
// Where the length of arc = 2πr = 2 * π * 45 = 282.6
const animateRing = () => {
  const ringArray = `${(calcPercent() * ring).toFixed(0)} 283`;
  document.getElementById('base-timer-path-remaining').setAttribute('stroke-dasharray', ringArray);
  // Animate clockhand
  document.getElementById('clockhand').style.transform = 'rotate(-' + (calcPercent() * 360) + 'deg)';
};

render(remaining)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文