鼠標快速在導航項之間來回移動,滑塊會卡在某位置停止響應。
move() 中每次調用 setInterval 前**未清除上一個定時器**,導致多個定時器並行修改同一元素 style.left,互相覆蓋、邏輯混亂。
var timer = null; // 模塊級變量持有定時器 ID
function move(a) {
clearInterval(timer); // 關鍵:清除舊定時器
var target = a * 130;
var current = parseInt(tt.style.left) || 0;
if (current > target) {
timer = setInterval(() => moveLeft(target), 30);
} else if (current < target) {
timer = setInterval(() => moveRight(target), 30);
}
}
定時器 30ms 間隔在高刷屏上不夠平滑,建議用 requestAnimationFrame 實現緩動動畫:
function animateTo(target) {
var start = parseInt(tt.style.left) || 0;
var duration = 300; // ms
var startTime = performance.now();
function step(now) {
var elapsed = now - startTime;
var progress = Math.min(elapsed / duration, 1);
// ease-out
var eased = 1 - Math.pow(1 - progress, 3);
tt.style.left = (start + (target - start) * eased) + 'px';
if (progress < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
timer 變量,每次 move 先 clearInterval。a * 130,避免重複解析。Math.min/max 確保不超出範圍。transition: left 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) 純 CSS 動畫,完全避免 JS 定時器。