我正在我正在工作的网站上制作图库。它会自动滚动浏览照片,但用户也可以暂停并手动滚动。我遇到的问题是自动滚动定时。我做了一个setInterval()
每毫秒运行一次autoScroll()
。在autoScroll()
中,它会增加一个变量,然后滚动,并将变量设置为3000,然后将其设置回0。我这样做是为了代替在直接调用滚动的setInterval上使用3000毫秒,我可以在用户暂停或手动滚动时重置计时器。理论上,它应该每3秒滚动一次。但这要慢得多。在Chrome中,大约需要12秒,在Firefox中大约需要45秒。我尚未在其他任何浏览器上对其进行测试。
当前,我直接在计算机上运行它,因此尚不涉及服务器。因此,应该是代码问题,而不是服务器问题。
以下是脚本引用的相关HTML:
<table>
<tr>
<th>
<button id="left">❮</button>
</th>
<th id="picture" colspan="3"></th>
<th>
<button id="right">❯</button>
</th>
</tr>
<tr>
<td></td>
<td id="pause">❚❚</td>
<td id="below"><span id="caption" style="text-align: center;"></span><br><span id="dots"
style="text-align: center;"></span></td>
<td style="width: 5%"></td>
<td></td>
</tr>
</table>
这是javascript:
var pics = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg", "pic5.jpg"];
var captions = ["caption 1", "caption 2", "caption 3", "caption 4", "caption 5",];
var play = true;
var position = 0;
var direction = 0;
var auto = 0;
for (var x = 1; x < pics.length + 1; x++) {
dots.innerHTML = dots.innerHTML + '<input id="dot' + x.toString() + '" type="radio" name="dot" value="' + x.toString() + '"><label for="dot' + x.toString() + '">●</label>';
}
dot1.checked = true;
picture.innerHTML = '<img src="' + pics[0] + '" />';
caption.innerHTML = captions[0];
function move() {
var positionIndex = position + 1;
position = position + direction;
if (position == -1) { position = pics.length - 1; }
if (position == pics.length) { position = 0; }
positionIndex = position + 1;
picture.innerHTML = '<img src="' + pics[position] + '" />';
caption.innerHTML = captions[position];
document.getElementById("dot" + positionIndex.toString()).checked = true;
auto = 0;
}
left.onclick = function () {
direction = -1;
move();
}
right.onclick = function () {
direction = 1;
move();
}
dots.onclick = function () {
position = parseInt(document.querySelector('input[name = "dot"]:checked').value) - 1;
positionIndex = position + 1;
picture.innerHTML = '<img src="' + pics[position] + '" />';
caption.innerHTML = captions[position];
document.getElementById("dot" + positionIndex.toString()).checked = true;
auto = 0;
}
pause.onclick = function () {
if (play) {
play = false;
pause.innerHTML = "▶";
} else {
play = true;
pause.innerHTML = "❚❚";
}
auto = 0;
}
function autoScroll() {
auto++
if (auto == 3000 && play) {
direction = 1;
auto = 0;
move();
}
}
window.setInterval(autoScroll, 1);
答案 0 :(得分:1)
由于缓解了崩溃/幽灵漏洞,所有浏览器都故意使计时器的精度降低。我不确定setInterval是否被视为高分辨率计时器,但它也可能会受到影响。
https://developers.google.com/web/updates/2018/02/meltdown-spectre
即使在此之前,setInterval也不保证它将在规定的时间后准确触发。如果浏览器很忙,它会变得更糟。
简而言之,您应该检查当前时间(例如,使用+(new Date())),并查看实际经过了多少时间,而不是将每个setInterval的变量增加1。
...
auto = +(new Date());
}
function autoScroll() {
var date = +(new Date());
if(auto > date + 3000 && play) {
direction = 1;
auto = date;
move();
}
}
或者,正如已经建议的那样,放弃使用较短的setInterval的想法,保存对计时器的引用,然后取消该计时器,如果用户单击,则重新启动它。
...
resetTimer();
}
function autoScroll() {
if(play) {
direction = 1;
resetTimer();
move();
}
}
function resetTimer() {
if(timer) {
window.clearInterval(timer);
}
timer = window.setInterval(autoScroll,3000);
}
timer = window.setInterval(autoScroll,3000);