【问题标题】:How to create a stopwatch using JavaScript?如何使用 JavaScript 创建秒表?
【发布时间】:2023-04-11 07:11:01
【问题描述】:
if(stopwatch >= track[song].duration)

track[song].duration 查找 soundcloud 轨道的持续时间。

我希望创建一个秒表函数,当您单击swap ID stopwatch 时开始计算毫秒数,这样当该函数被“单击”一段时间后,if 函数就会执行某些操作。就我而言,替换图像。并且该功能会在再次单击时自行重置。

就像stopwatch = current time - clicked time 我该如何设置clicked time

current time = new Date().getTime(); ?这是以毫秒为单位的吗?

$('#swap').click(function()...

【问题讨论】:

  • javascript 中的计时器通常是通过在特定时刻创建 Date 对象来设置的。然后,您可以减去 Dates 以获得以毫秒为单位的差异。但你似乎知道这一点。似乎缺少的是您要为其创建 Date 对象的事件。

标签: javascript jquery


【解决方案1】:

两种原生解决方案

  • performance.now --> 调用 ... 花费了 6.414999981643632 毫秒。
  • console.time --> 调用 ... 花费了 5.815 毫秒

两者的区别在于精度。

有关用法和说明,请继续阅读。



Performance.now(用于微秒精度)

    var t0 = performance.now();
    doSomething();
    var t1 = performance.now();

    console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
            
    function doSomething(){    
       for(i=0;i<1000000;i++){var x = i*i;}
    }

performance.now

与 JavaScript 可用的其他计时数据不同(例如 Date.now), Performance.now() 返回的时间戳不是 仅限于一毫秒的分辨率。相反,它们代表时间 作为浮点数精度高达微秒

与 Date.now() 不同的是,Performance.now() 返回的值 始终以恒定速率增加,与系统时钟无关 (可以手动调整或通过 NTP 等软件进行调整)。 否则,performance.timing.navigationStart + performance.now() 将 大约等于 Date.now()。



console.time

示例:timeEnd 包裹在 setTimeout 中用于模拟)

console.time('Search page');
  doSomething();
console.timeEnd('Search page');
 

 function doSomething(){    
       for(i=0;i<1000000;i++){var x = i*i;}
 }

您可以为不同的操作更改 Timer-Name。

【讨论】:

  • 值得一提的是performance.nowblow up IE 9,如果这对您的应用仍然很重要并且您没有进行编译。
【解决方案2】:

您会看到演示代码只是一个开始/停止/重置毫秒计数器。如果您想在时间上进行奇特的格式化,那完全取决于您。这应该足以让您入门。

这是一个有趣的小项目。这是我的处理方法

var Stopwatch = function(elem, options) {

  var timer = createTimer(),
    startButton = createButton("start", start),
    stopButton = createButton("stop", stop),
    resetButton = createButton("reset", reset),
    offset,
    clock,
    interval;

  // default options
  options = options || {};
  options.delay = options.delay || 1;

  // append elements     
  elem.appendChild(timer);
  elem.appendChild(startButton);
  elem.appendChild(stopButton);
  elem.appendChild(resetButton);

  // initialize
  reset();

  // private functions
  function createTimer() {
    return document.createElement("span");
  }

  function createButton(action, handler) {
    var a = document.createElement("a");
    a.href = "#" + action;
    a.innerHTML = action;
    a.addEventListener("click", function(event) {
      handler();
      event.preventDefault();
    });
    return a;
  }

  function start() {
    if (!interval) {
      offset = Date.now();
      interval = setInterval(update, options.delay);
    }
  }

  function stop() {
    if (interval) {
      clearInterval(interval);
      interval = null;
    }
  }

  function reset() {
    clock = 0;
    render(0);
  }

  function update() {
    clock += delta();
    render();
  }

  function render() {
    timer.innerHTML = clock / 1000;
  }

  function delta() {
    var now = Date.now(),
      d = now - offset;

    offset = now;
    return d;
  }

  // public API
  this.start = start;
  this.stop = stop;
  this.reset = reset;
};


// basic examples
var elems = document.getElementsByClassName("basic");

for (var i = 0, len = elems.length; i < len; i++) {
  new Stopwatch(elems[i]);
}


// programmatic examples
var a = document.getElementById("a-timer");
aTimer = new Stopwatch(a);
aTimer.start();

var b = document.getElementById("b-timer");
bTimer = new Stopwatch(b, {
  delay: 100
});
bTimer.start();

var c = document.getElementById("c-timer");
cTimer = new Stopwatch(c, {
  delay: 456
});
cTimer.start();

var d = document.getElementById("d-timer");
dTimer = new Stopwatch(d, {
  delay: 1000
});
dTimer.start();
.stopwatch {
  display: inline-block;
  background-color: white;
  border: 1px solid #eee;
  padding: 5px;
  margin: 5px;
}

.stopwatch span {
  font-weight: bold;
  display: block;
}

.stopwatch a {
  padding-right: 5px;
  text-decoration: none;
}
<h2>Basic example; update every 1 ms</h2>

<p>click <code>start</code> to start a stopwatch</p>

<pre>
var elems = document.getElementsByClassName("basic");
  
for (var i=0, len=elems.length; i&lt;len; i++) {
  new Stopwatch(elems[i]);
}
</pre>
<div class="basic stopwatch"></div>
<div class="basic stopwatch"></div>

<hr>
<h2>Programmatic example</h2>

<p><strong>Note:</strong> despite the varying <code>delay</code> settings, each stopwatch displays the correct time (in seconds)</p>

<pre>
var a = document.getElementById("a-timer");
aTimer = new Stopwatch(a);
aTimer.start();
</pre>
<div class="stopwatch" id="a-timer"></div>1 ms<br>

<pre>
var b = document.getElementById("b-timer");
bTimer = new Stopwatch(b, {delay: 100});
bTimer.start();
</pre>
<div class="stopwatch" id="b-timer"></div>100 ms<br>

<pre>
var c = document.getElementById("c-timer");
cTimer = new Stopwatch(c, {delay: 456});
cTimer.start();
</pre>
<div class="stopwatch" id="c-timer"></div>456 ms<br>

<pre>
var d = document.getElementById("d-timer");
dTimer = new Stopwatch(d, {delay: 1000});
dTimer.start();
</pre>
<div class="stopwatch" id="d-timer"></div>1000 ms<br>

为它获取一些基本的 HTML 包装器

<!-- create 3 stopwatches -->
<div class="stopwatch"></div>
<div class="stopwatch"></div>
<div class="stopwatch"></div>

从那里开始使用非常简单

var elems = document.getElementsByClassName("stopwatch");

for (var i=0, len=elems.length; i<len; i++) {
    new Stopwatch(elems[i]);
}

作为奖励,您还可以获得用于计时器的可编程 API。这是一个使用示例

var elem = document.getElementById("my-stopwatch");
var timer = new Stopwatch(elem, {delay: 10});

// start the timer
timer.start();

// stop the timer
timer.stop();

// reset the timer
timer.reset();

jQuery 插件

至于 jQuery 部分,一旦你有了上面的代码组合,编写一个 jQuery 插件 就很简单了

(function($) {
    var Stopwatch = function(elem, options) {
    // code from above...
    };

    $.fn.stopwatch = function(options) {
    return this.each(function(idx, elem) {
        new Stopwatch(elem, options);
    });
    };
})(jQuery);

jQuery插件使用:

// all elements with class .stopwatch; default delay (1 ms)
$(".stopwatch").stopwatch();

// a specific element with id #my-stopwatch; custom delay (10 ms)
$("#my-stopwatch").stopwatch({delay: 10});

jsbin.com demo

【讨论】:

  • 在我的特殊情况下,我调用 timer.start() 并且它工作正常,但是当我必须使用 timer.stop() 时,'timer' 变量超出范围,什么我应该这样做吗?
  • 感谢您的关注。无论如何,我几个小时前就解决了这个问题。
  • 那是一段非常好的代码!但是,有一个问题。如果在定时器开启时​​系统时间发生变化,定时器的值会跳跃。您将如何解决这个问题?
  • @Tigran 如果用户重新启动计算机或刷新浏览器选项卡,计时器也会停止工作。这些不是“陷阱”。除非有某种合理的无关要求,否则我不会编写代码来解决这些“问题”。
  • @maček,我问是因为我在我的应用程序中使用了计时器,并且担心这种行为。我想,也许你对如何解决这个问题有任何想法(当然,其他人也可以使用)。
【解决方案3】:

一个简单易用的时钟,别忘了我;)

var x;
var startstop = 0;

function startStop() { /* Toggle StartStop */

  startstop = startstop + 1;

  if (startstop === 1) {
    start();
    document.getElementById("start").innerHTML = "Stop";
  } else if (startstop === 2) {
    document.getElementById("start").innerHTML = "Start";
    startstop = 0;
    stop();
  }

}


function start() {
  x = setInterval(timer, 10);
} /* Start */

function stop() {
  clearInterval(x);
} /* Stop */

var milisec = 0;
var sec = 0; /* holds incrementing value */
var min = 0;
var hour = 0;

/* Contains and outputs returned value of  function checkTime */

var miliSecOut = 0;
var secOut = 0;
var minOut = 0;
var hourOut = 0;

/* Output variable End */


function timer() {
  /* Main Timer */


  miliSecOut = checkTime(milisec);
  secOut = checkTime(sec);
  minOut = checkTime(min);
  hourOut = checkTime(hour);

  milisec = ++milisec;

  if (milisec === 100) {
    milisec = 0;
    sec = ++sec;
  }

  if (sec == 60) {
    min = ++min;
    sec = 0;
  }

  if (min == 60) {
    min = 0;
    hour = ++hour;

  }


  document.getElementById("milisec").innerHTML = miliSecOut;
  document.getElementById("sec").innerHTML = secOut;
  document.getElementById("min").innerHTML = minOut;
  document.getElementById("hour").innerHTML = hourOut;

}


/* Adds 0 when value is <10 */


function checkTime(i) {
  if (i < 10) {
    i = "0" + i;
  }
  return i;
}

function reset() {


  /*Reset*/

  milisec = 0;
  sec = 0;
  min = 0
  hour = 0;

  document.getElementById("milisec").innerHTML = "00";
  document.getElementById("sec").innerHTML = "00";
  document.getElementById("min").innerHTML = "00";
  document.getElementById("hour").innerHTML = "00";

}
<h1>
  <span id="hour">00</span> :
  <span id="min">00</span> :
  <span id="sec">00</span> :
  <span id="milisec">00</span>
</h1>

<button onclick="startStop()" id="start">Start</button>
<button onclick="reset()">Reset</button>

【讨论】:

    【解决方案4】:
    function StopWatch() {
        let startTime, endTime, running, duration = 0
        
        this.start = () => {
            if (running) console.log('its already running')
            else {
                running = true
                startTime = Date.now()
            }
        }
    
        this.stop = () => {
            if (!running) console.log('its not running!')
            else {
                running = false
                endTime = Date.now()
    
                const seconds = (endTime - startTime) / 1000
                duration += seconds
            }
        }
    
        this.restart = () => {
            startTime = endTime = null
            running = false
            duration = 0
        }
        
        Object.defineProperty(this, 'duration', {
            get: () => duration.toFixed(2)
        })
    
    }
    
    const sw =  new StopWatch()
    
    sw.start()
    sw.stop()
    
    sw.duration
    

    【讨论】:

      【解决方案5】:

      这是我对这个问题的简单看法,我希望有一天它可以帮助某人,某处......

      let output = document.getElementById('stopwatch');
      let ms = 0;
      let sec = 0;
      let min = 0;
      
      function timer() {
          ms++;
          if(ms >= 100){
              sec++
              ms = 0
          }
          if(sec === 60){
              min++
              sec = 0
          }
          if(min === 60){
              ms, sec, min = 0;
          }
      
          //Doing some string interpolation
          let milli = ms < 10 ? `0`+ ms : ms;
          let seconds = sec < 10 ? `0`+ sec : sec;
          let minute = min < 10 ? `0` + min : min;
      
          let timer= `${minute}:${seconds}:${milli}`;
          output.innerHTML =timer;
      };
      //Start timer
      function start(){
       time = setInterval(timer,10);
      }
      //stop timer
      function stop(){
          clearInterval(time)
      }
      //reset timer
      function reset(){
          ms = 0;
          sec = 0;
          min = 0;
      
          output.innerHTML = `00:00:00`
      }
      const startBtn = document.getElementById('startBtn');
      const stopBtn =  document.getElementById('stopBtn');
      const resetBtn = document.getElementById('resetBtn');
      
      startBtn.addEventListener('click',start,false);
      stopBtn.addEventListener('click',stop,false);
      resetBtn.addEventListener('click',reset,false);
          <p class="stopwatch" id="stopwatch">
              <!-- stopwatch goes here -->
          </p>
          <button class="btn-start" id="startBtn">Start</button>
          <button class="btn-stop" id="stopBtn">Stop</button>
          <button class="btn-reset" id="resetBtn">Reset</button>

      【讨论】:

      • 有趣的是,计数器的运行速度比“实时”慢。如果你比较秒,你可以看到它更慢。可能是因为 if 语句需要一些时间来检查,然后速度变慢(即使它只有几毫秒,总结一下)?
      【解决方案6】:

      Mosh Hamedani 的解决方案

      创建 StopWatch 函数构造函数。

      定义4个局部变量

      1. 开始时间
      2. 结束时间
      3. 正在运行
      4. 持续时间设置为 0

      接下来创建3个方法

      1. 开始
      2. 停止
      3. 重置

      启动方法

      • 检查 isRunning 是否为真,如果是则抛出 start 不能被调用两次的错误。
      • 将 isRunning 设置为 true
      • 将当前 Date 对象分配给 startTime。

      停止方法

      • 检查 isRunning 是否为 false,如果是则抛出无法调用两次 stop 的错误。
      • 将 isRunning 设置为 false
      • 将当前 Date 对象分配给 endTime。
      • 通过 endTime 和 startTime 日期对象计算秒数
      • 以秒为单位增加持续时间

      重置方法:

      • 重置所有局部变量。

      只读属性

      如果您想访问持续时间局部变量,您需要使用 Object.defineProperty 定义一个属性。 当您要创建 只读 属性时,它很有用。

      Object.defineProperty 需要 3 个参数

      • 要定义属性的对象(在本例中为当前对象 (this))
      • 物业名称
      • key 属性的值。

      • 我们想要创建一个只读属性,因此我们将 object 作为 value 传递。 该对象包含一个返回持续时间 local 变量的 get 方法。 这样我们就不能只更改属性get it

      诀窍是使用 Date() 对象来计算时间。

      参考下面的代码

      function StopWatch() {
      
      
      let startTime,
          endTime,
          isRunning,
          duration = 0;
      
        this.start = function () {
          if (isRunning) throw new Error("StopWatch has already been started.");
      
          isRunning = true;
      
          startTime = new Date();
        };
      
      
      
      this.stop = function () {
          if (!isRunning) throw new Error("StopWatch has already been stop.");
      
          isRunning = false;
      
          endTime = new Date();
      
          const seconds = (endTime.getTime() - startTime.getTime()) / 1000;
          duration += seconds;
        };
      
        this.reset = function () {
          duration = 0;
          startTime = null;
          endTime = null;
          isRunning = false;
        };
      
        Object.defineProperty(this, "duration", {
          get: function () {
            return duration;
          },
        });
      }
      
      const sw = new StopWatch();
      

      【讨论】:

      • 我的 sw.duration 总是 0
      【解决方案7】:

      在对 mace 提供的代码进行了一些修改之后,我最终构建了一个秒表。 https://codepen.io/truestbyheart/pen/EGELmv

        <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <meta http-equiv="X-UA-Compatible" content="ie=edge" />
          <title>Stopwatch</title>
          <style>
          #center {
           margin: 30%  30%;
           font-family: tahoma;
           }
          .stopwatch {
               border:1px solid #000;
               background-color: #eee;
               text-align: center;
               width:656px;
               height: 230px;
               overflow: hidden;
           }
           .stopwatch span{
               display: block;
               font-size: 100px;
           }
           .stopwatch p{
               display: inline-block;
               font-size: 40px;
           }
           .stopwatch a{
             font-size:45px;
           }
           a:link,
           a:visited{
               color :#000;
               text-decoration: none;
               padding: 12px 14px;
               border: 1px solid #000;
           }
          </style>
        </head>
        <body>
            <div id="center">
                  <div class="timer stopwatch"></div>
            </div>
      
          <script>
            const Stopwatch = function(elem, options) {
              let timer = createTimer(),
                startButton = createButton("start", start),
                stopButton = createButton("stop", stop),
                resetButton = createButton("reset", reset),
                offset,
                clock,
                interval,
                hrs = 0,
                min = 0;
      
              // default options
              options = options || {};
              options.delay = options.delay || 1;
      
              // append elements
              elem.appendChild(timer);
              elem.appendChild(startButton);
              elem.appendChild(stopButton);
              elem.appendChild(resetButton);
      
              // initialize
              reset();
      
              // private functions
              function createTimer() {
                return document.createElement("span");
              }
      
              function createButton(action, handler) {
                if (action !== "reset") {
                  let a = document.createElement("a");
                  a.href = "#" + action;
                  a.innerHTML = action;
                  a.addEventListener("click", function(event) {
                    handler();
                    event.preventDefault();
                  });
                  return a;
                } else if (action === "reset") {
                  let a = document.createElement("a");
                  a.href = "#" + action;
                  a.innerHTML = action;
                  a.addEventListener("click", function(event) {
                    clean();
                    event.preventDefault();
                  });
                  return a;
                }
              }
      
              function start() {
                if (!interval) {
                  offset = Date.now();
                  interval = setInterval(update, options.delay);
                }
              }
      
              function stop() {
                if (interval) {
                  clearInterval(interval);
                  interval = null;
                }
              }
      
              function reset() {
                clock = 0;
                render(0);
              }
      
              function clean() {
                min = 0;
                hrs = 0;
                clock = 0;
                render(0);
              }
      
              function update() {
                clock += delta();
                render();
              }
      
              function render() {
                if (Math.floor(clock / 1000) === 60) {
                  min++;
                  reset();
                  if (min === 60) {
                    min = 0;
                    hrs++;
                  }
                }
                timer.innerHTML =
                  hrs + "<p>hrs</p>" + min + "<p>min</p>" + Math.floor(clock / 1000)+ "<p>sec</p>";
              }
      
              function delta() {
                var now = Date.now(),
                  d = now - offset;
      
                offset = now;
                return d;
              }
            };
      
            // Initiating the Stopwatch
            var elems = document.getElementsByClassName("timer");
      
            for (var i = 0, len = elems.length; i < len; i++) {
              new Stopwatch(elems[i]);
            }
          </script>
        </body>
      </html>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-07
        • 2012-12-09
        • 1970-01-01
        • 2017-11-06
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多