目前正在开发一个项目,需要在一页上有两个计时器。定时器需要有一个启动按钮,并且两者都有不同的计时(即定时器 1 持续 10 秒,定时器 2 持续 20 秒)。这是我正在使用的脚本,但我不知道如何复制计时器并让每个计时器独立工作。
有没有人可以轻松地将这个脚本更改为两个计时器的功能脚本?
<html>
<head>
<script language="JavaScript" type="text/javascript">
var interval;
var minutes = 0;
var seconds = 10;
function countdown(element) {
interval = setInterval(function(timer) {
var el = document.getElementById(element);
if(seconds == 0) {
if(minutes == 0) {
(el.innerHTML = "STOP!");
clearInterval(interval);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? '' : '';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
seconds--;
}, 1000);
}
var start = document.getElementById('start');
start.onclick = function(timer) {
if (!interval) {
countdown('countdown');
}
}
</script>
</head>
<body>
<div id='countdown'></div>
<input type="button" onclick="countdown('countdown');this.disabled = true;" value="Start" />
</body>
</html>
您所做的一些事情会阻止您扩展代码。如果您想要一个可重用的计时器,则不能硬设置它将使用的变量。因此,第一件事是删除顶部的三个变量并在函数范围内重新创建它们。
这样,每次调用该函数时,都会为其执行创建一组新的变量。
分钟和秒可能最好作为参数传递,并且间隔应该在函数范围内定义。
其次,您在内联和脚本内设置点击处理程序。摆脱其中之一(最好摆脱内联版本)。
然后,您有一个计时器变量作为单击处理程序和 setInterval 的参数,但从未使用过。该变量将被设置为事件处理程序上的单击事件(并且再次未使用),并且在 setInterval 上未定义。所以他们真的不应该在那里。
您可能想知道的一个性能问题是您每秒都在对计数器进行 DOM 查找。您应该在每个函数调用开始时获取一次并缓存它。
那时,你的功能或多或少会像这样
function countdown(element, minutes, seconds) {
// Fetch the display element
var el = document.getElementById(element);
// Set the timer
var interval = setInterval(function() {
if(seconds == 0) {
if(minutes == 0) {
(el.innerHTML = "STOP!");
clearInterval(interval);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? '' : '';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
seconds--;
}, 1000);
}
你的设置或多或少是这样的
//Start as many timers as you want
var start1 = document.getElementById('timer1');
var start2 = document.getElementById('timer2');
start1.onclick = function() {
countdown('countdown1', 0, 15);
}
start2.onclick = function() {
countdown('countdown2', 0, 10);
}
当然,你需要额外的按钮和计数器
<div id='countdown1'></div>
<div id='countdown2'></div>
<input id="timer1" type="button" value="Start timer 1" />
<input id="timer2" type="button" value="Start timer 2" />
工作示例:http://codepen.io/anon/pen/Jmpcq/?editors=101
-- 注意:对于精确计时器,
setInterval()
可能不是一个好的选择,因为不能保证精确的间隔,并且它跟踪的时间可能会延迟一段时间。对于精确时间至关重要的应用程序,还有其他方法(例如 https://sitepoint.com/creating-accurate-timers-in-javascript 和 https://html5rocks.com/en/tutorials/webperformance/usertimin ),感谢@KaiKarver 在评论中指出。
虽然很长但很有效
let d = document,
id = 'getElementById',
time = {
//Multiple Timers
//[current time, time setting, (pause/running), HTML section#timer]
timer1: ['0:10', '0:10', 0, d[id]('timer1')],
timer2: ['2:30', '2:30', 0, d[id]('timer2')],
timer3: ['5:00', '5:00', 0, d[id]('timer3')],
//Manage Timer Functions
reset: function(t) {time[t][0] = time[t][1];},
pause: function(t) {time[t][2] = 0;time.state(t,'pause');time.button(t,'resume');},
resume: function(t) {time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
set: function(t,s) {time[t][0] = s; time[t][1] = s;},
state: function(t,s) {time[t][3].setAttribute('state',s);},
button: function(t,s) {time[t][3].querySelector('div').innerHTML = s;},
cancel: function(t) {time[t][2] = 0;time.reset(t);time.state(t,'');time.button(t,'start');time.setTimer(t);},
start: function(t) {time.reset(t);time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
getTimers: function() {return Object.keys(time).filter(function (n) {return n.indexOf("ti")==0;});},
setTimer: function(t) {time[t][3].querySelector('span').innerHTML = time[t][0]},
setTimers: function(x) {
let times = time.getTimers();
for (var i=0,t;i<times.length;i++) {t=times[i];
if(time[t][2]||x){time[t][3].querySelector('span').innerHTML = time[t][0]}
}
},
};
//handle seconds passed
function convertSeconds(s=0) {return new Date(s*1000).toISOString().substr(11,8).replace(/^(00:0(?=[1-9])|00:|0)/gm, '')}
function toSeconds(t) {t=t.split(':').reverse();return (t[2]*3600||0)+(t[1]*60||0)+t[0]*1||0;}
//set HTML times onLoad
time.setTimers(1)
function runTimer(times){times = time.getTimers();time.setTimers();
function run(t,s,l){if(t&&t[2]){s=toSeconds(t[0]);t[0]=s?convertSeconds(s-1):'00:00'&&(time.cancel(l));}}
for (var i=0,t;i<times.length;i++) {run(time[times[i]],'',times[i])}
}
//run timer every second reguardless of whether timer is paused or running
setInterval(runTimer, 1000)
body {
background: #e6e9f0;
user-select: none;
font-family: "SF Pro Display", Helvetica Neue, Arial, Helvetica, Geneva, sans-serif;
font-size: 14px;
}
div, span {display: inline-block;}
span {min-width: 60px;}
#time > section {
padding: 10px 20px;
background: white;
margin: 10px;
border-radius: 4px;
transition: .15s ease-in-out 0s;
text-transform: capitalize;
}
#time > section:hover {box-shadow: 0px 0px 0px 2px #A8D1FD;}
#time > section > div{text-shadow: 0 1px 1px rgba(0,0,0,0.3);transition: .1s ease-in-out 0s;}
#time > section > div:nth-of-type(2){background: #cfd3dd;opacity: 1;}
#time > section[state=""] > div:nth-of-type(2) {opacity: 0;}
#time > section > div{
background: #368ad2;
color: white;
padding: 6px 10px;
margin: 0 5px;
min-width: 50px;
text-align: center;
border-radius: 4px;
}
<section id="time">
<section id="timer1" state="">
<span>0:00</span>
<div onClick="time[this.innerHTML]('timer1')">start</div>
<div onClick="time.cancel('timer1')">cancel</div>
</section>
<section id="timer2" state="">
<span>0:00</span>
<div onClick="time[this.innerHTML]('timer2')">start</div>
<div onClick="time.cancel('timer2')">cancel</div>
</section>
<section id="timer3" state="">
<span>0:00</span>
<div onClick="time[this.innerHTML]('timer3')">start</div>
<div onClick="time.cancel('timer3')">cancel</div>
</section>
</section>
var interval;
var countdown1 = {
minutes:0,
seconds: 10
};
var countdown2 = {
minutes:0,
seconds: 2
}
function countdown(element) {
alert(element);
var cd;
element === 'countdown1' ? cd = countdown1 : cd = countdown2;
interval = setInterval(function(timer) {
var el = document.getElementById(element);
if(cd.seconds == 0) {
if(cd.minutes == 0) {
(el.innerHTML = "STOP!");
clearInterval(interval);
return;
} else {
cd.minutes--;
cd.seconds = 60;
}
}
if(cd.minutes > 0) {
var minute_text = cd.minutes + (cd.minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? '' : '';
el.innerHTML = minute_text + ' ' + cd.seconds + ' ' + second_text + '';
cd.seconds--;
}, 1000);
}
var start = document.getElementById('start');
<div id='countdown'></div>
<input type="button" onclick="countdown('countdown1');this.disabled = true;" value="Start" />
<div id="countdown1"></div>
<input type="button" onclick="countdown('countdown2');this.disabled = true;" value="Start" />
<div id="countdown2"></div>
let d = document,
id = 'getElementById',
time = {
//Multiple Timers
//[current time, time setting, (pause/running), HTML section#timer]
timer1: ['0:10', '0:10', 0, d[id]('timer1')],
timer2: ['2:30', '2:30', 0, d[id]('timer2')],
timer3: ['5:00', '5:00', 0, d[id]('timer3')],
//Manage Timer Functions
reset: function(t) {time[t][0] = time[t][1];},
pause: function(t) {time[t][2] = 0;time.state(t,'pause');time.button(t,'resume');},
resume: function(t) {time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
set: function(t,s) {time[t][0] = s; time[t][1] = s;},
state: function(t,s) {time[t][3].setAttribute('state',s);},
button: function(t,s) {time[t][3].querySelector('div').innerHTML = s;},
cancel: function(t) {time[t][2] = 0;time.reset(t);time.state(t,'');time.button(t,'start');time.setTimer(t);},
start: function(t) {time.reset(t);time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
getTimers: function() {return Object.keys(time).filter(function (n) {return n.indexOf("ti")==0;});},
setTimer: function(t) {time[t][3].querySelector('span').innerHTML = time[t][0]},
setTimers: function(x) {
let times = time.getTimers();
for (var i=0,t;i<times.length;i++) {t=times[i];
if(time[t][2]||x){time[t][3].querySelector('span').innerHTML = time[t][0]}
}
},
};
//handle seconds passed
function convertSeconds(s=0) {return new Date(s*1000).toISOString().substr(11,8).replace(/^(00:0(?=[1-9])|00:|0)/gm, '')}
function toSeconds(t) {t=t.split(':').reverse();return (t[2]*3600||0)+(t[1]*60||0)+t[0]*1||0;}
//set HTML times onLoad
time.setTimers(1)
function runTimer(times){times = time.getTimers();time.setTimers();
function run(t,s,l){if(t&&t[2]){s=toSeconds(t[0]);t[0]=s?convertSeconds(s-1):'00:00'&&(time.cancel(l));}}
for (var i=0,t;i<times.length;i++) {run(time[times[i]],'',times[i])}
}
//run timer every second reguardless of whether timer is paused or running
setInterval(runTimer, 1000)
body {
background: #e6e9f0;
user-select: none;
font-family: "SF Pro Display", Helvetica Neue, Arial, Helvetica, Geneva, sans-serif;
font-size: 14px;
}
div, span {display: inline-block;}
span {min-width: 60px;}
#time > section {
padding: 10px 20px;
background: white;
margin: 10px;
border-radius: 4px;
transition: .15s ease-in-out 0s;
text-transform: capitalize;
}
#time > section:hover {box-shadow: 0px 0px 0px 2px #A8D1FD;}
#time > section > div{text-shadow: 0 1px 1px rgba(0,0,0,0.3);transition: .1s ease-in-out 0s;}
#time > section > div:nth-of-type(2){background: #cfd3dd;opacity: 1;}
#time > section[state=""] > div:nth-of-type(2) {opacity: 0;}
#time > section > div{
background: #368ad2;
color: white;
padding: 6px 10px;
margin: 0 5px;
min-width: 50px;
text-align: center;
border-radius: 4px;
}
<section id="time">
<section id="timer1" state="">
<span>0:00</span>
<div onClick="time[this.innerHTML]('timer1')">start</div>
<div onClick="time.cancel('timer1')">cancel</div>
</section>
<section id="timer2" state="">
<span>0:00</span>
<div onClick="time[this.innerHTML]('timer2')">start</div>
<div onClick="time.cancel('timer2')">cancel</div>
</section>
<section id="timer3" state="">
<span>0:00</span>
<div onClick="time[this.innerHTML]('timer3')">start</div>
<div onClick="time.cancel('timer3')">cancel</div>
</section>
</section>