我制作了一个JavaScript秒表,它通过每秒输入一个变量的值来工作(使用setInterval(stopwatchValue, 1000)
)。我有一些问题:如果用户点击暂停,比如3.8秒,实际的暂停值将是3秒(当他们点击恢复时,秒表将从3.0秒而不是3.8秒继续。)
我有解决方案来解决这个问题。我的想法是通过像setInterval(stopwatchValue, 1)
这样的事情每隔一秒更新一次秒表。
我的问题是:浏览器每隔一秒就处理这个代码太多了:
function stopwatchValue("result") {
document.getElementById("result").innerHTML = timer;
timer++;
}
另外:有些人说如果可以,你应该多次避免访问DOM。在我的情况下,如果我用以下代码替换上面的代码,它会工作吗?
var displayResultHere = document.getElementById("result");
function stopwatchValue("result") {
displayResultHere = timer;
timer++;
}
我的秒表:hntr.atwebpages.com/stopwatch/stopwatch.html
答案 0 :(得分:0)
您需要的是可变延迟。
SetInterval缺乏精确度仍可用于更新用户看到的内容。
有什么不酷的是,舍入效果意味着我可以坐下来快速点击开始和停止反复几个小时,从来没有看到这个东西滴答一秒钟。
你需要做的是点击时间戳,做数学计算以找到实际持续时间(开始时花费的时间),计算应显示的内容,并设置一次(每次开始点击)变量延迟之前SetInterval的一秒钟滴答声再次开始。
这样做,没有任何点击会减慢你的时钟。
答案 1 :(得分:0)
以下是StopWatch的示例。我刚刚做到了。如果您知道如何阅读本网站上必须包含的代码,那么应该很容易理解。
//<![CDATA[
/* external.js */
var doc, bod, htm, M, I, S, Q, StopWatch, old = onload; // for use on other loads
onload = function(){ // load wrapper - not indented to save space
if(old)old(); // change old var name above and here if using technique on other pages
doc = document; bod = doc.body; htm = doc.documentElement;
M = function(tag){
return doc.createElement(tag);
}
I = function(id){
return doc.getElementById(id);
}
S = function(selector, within){
var w = within || doc;
return w.querySelector(selector);
}
Q = function(selector, within){
var w = within || doc;
return w.querySelectorAll(selector);
}
StopWatch = function(outputDiv, decimals, interval){
var dm = typeof decimals === 'number' ? decimals : 3;
var iv = typeof interval === 'number' ? interval : 10;
this.zero = '00:00:0'+(0).toFixed(dm); outputDiv.innerHTML = this.zero;
var st, si, et;
this.start = function(){
if(st === undefined){
st = Date.now();
}
else if(et !== undefined){
st = Date.now()-et+st; et = undefined;
}
si = setInterval(function(){
var t = Date.now()-st, h = Math.floor(t/3600000), hf = h*3600000, m = Math.floor((t-hf)/60000), mf = m*60000, s = Math.floor((t-hf-mf)/1000), sf = s*1000;
s = (s+(t-hf-mf-sf)/1000).toFixed(dm);
if(h.toString().match(/^\d$/))h = '0'+h;
if(m.toString().match(/^\d$/))m = '0'+m;
if(s.toString().match(/^\d(\.?\d*)?$/))s = '0'+s;
var out = h+':'+m+':'+s;
outputDiv.innerHTML = out;
}, iv);
return this;
}
this.stop = function(){
if(si){
if(et === undefined)et = Date.now();
clearInterval(si); si = undefined;
}
return this;
}
this.clear = function(){
this.stop(); st = et = undefined; outputDiv.innerHTML = this.zero;
return this;
}
}
I('f').onsubmit = function(){
return false;
}
var act = I('act'), clear = I('clear'), out = I('out');
var stopWatch = new StopWatch(out);
act.onclick = function(){
if(this.value === 'start'){
stopWatch.start(); this.value = 'stop';
}
else{
stopWatch.stop(); this.value = 'start';
}
}
clear.onclick = function(){
stopWatch.clear(); out.innerHTML = stopWatch.zero; act.value = 'start';
}
} // end load
//]]>
&#13;
/* external.css */
html,body{
padding:0; margin:0;
}
body{
background:#000; overflow-y:scroll;
}
.main{
width:940px; background:#ccc; padding:20px; margin:0 auto;
}
#out{
display:inline-block; width:85px; background:#fff; padding:5px 10px; cursor:default;
}
#act,#clear{
width:55px; cursor:pointer;
}
&#13;
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='viewport' content='width=device-width' />
<title>StopWatch</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div class='main'>
<form id='f' name='f'>
<div id='out'></div>
<input id='act' type='button' value='start' />
<input id='clear' type='button' value='reset' />
</form>
</div>
</body>
</html>
&#13;
答案 2 :(得分:-1)
不使用setTimeout
,而是使用requestAnimationFrame()
。
当计时器启动时,创建一个新的Date
,并在每个动画帧中创建一个新日期:减去两个以获得计时器的当前值。
将DOM元素缓存到变量中,就像您已经完成的那样。像这样:
var result_display = document.getElementById("result");
var timer_is_running = false;
var remembered_time = null;
var timer_start_time;
function start_timer() {
timer_is_running = true;
timer_start_time = new Date();
update_timer_value(accumulated_time);
}
function pause_timer() {
timer_is_running = false;
}
function update_timer_value(acc_time) {
var elapsed_time = new Date() - timer_start_time;
if (remembered_time) {
elapsed_time += remembered_time;
remembered_time = null;
}
var second_value = Math.floor(elapsed_time);
result_display.innerHTML = second_value;
if (timer_is_running) {
requestAnimationFrame(update_timer_value);
}
else {
remembered_time = elapsed_time;
}
}