首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JavaScript 自定義鼠標滾輪滾動距離:實現全屏滾動、頁面切換等交互效果

     編輯:程式設計綜合問答

核心需求

覆蓋瀏覽器默認滾動行為,每次滾輪滾動固定距離(如 700px),實現類似「親寶寶官網」的全屏翻頁效果。

現代解決方案:Wheel Event + scrollTo

基礎實現

let isScrolling = false;
const SCROLL_DISTANCE = 700; // 固定滾動距離
const SCROLL_DURATION = 800; // 動畫時長 ms

window.addEventListener('wheel', (e) => {
  if (isScrolling) return; // 防止動畫期間重複觸發
  
  e.preventDefault(); // 禁用默認滾動
  
  const direction = e.deltaY > 0 ? 1 : -1; // 向下/向上
  const targetY = window.scrollY + direction * SCROLL_DISTANCE;
  
  // 邊界檢查
  const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
  const clampedY = Math.max(0, Math.min(targetY, maxScroll));
  
  smoothScrollTo(clampedY);
}, { passive: false }); // 必須 passive: false 才能 preventDefault

function smoothScrollTo(targetY) {
  isScrolling = true;
  const startY = window.scrollY;
  const startTime = performance.now();
  
  function animate(currentTime) {
    const elapsed = currentTime - startTime;
    const progress = Math.min(elapsed / SCROLL_DURATION, 1);
    // 緩動函數
    const ease = 1 - Math.pow(1 - progress, 3); // cubic ease-out
    window.scrollTo(0, startY + (targetY - startY) * ease);
    
    if (progress < 1) {
      requestAnimationFrame(animate);
    } else {
      isScrolling = false;
    }
  }
  requestAnimationFrame(animate);
}

進階方案:IntersectionObserver + 全屏區塊鎖定

更適合「全屏輪播」場景,確保每次滾動精準對齊區塊:

const sections = document.querySelectorAll('.full-screen-section');
let currentIndex = 0;
let isAnimating = false;

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      currentIndex = Array.from(sections).indexOf(entry.target);
    }
  });
}, { threshold: 0.5 });

sections.forEach(sec => observer.observe(sec));

window.addEventListener('wheel', (e) => {
  if (isAnimating) return;
  e.preventDefault();
  
  const dir = e.deltaY > 0 ? 1 : -1;
  const nextIndex = Math.max(0, Math.min(currentIndex + dir, sections.length - 1));
  
  if (nextIndex !== currentIndex) {
    scrollToSection(nextIndex);
  }
}, { passive: false });

function scrollToSection(index) {
  isAnimating = true;
  sections[index].scrollIntoView({ behavior: 'smooth' });
  
  // 監聽滾動結束
  const onScrollEnd = () => {
    isAnimating = false;
    window.removeEventListener('scroll', onScrollEnd);
  };
  window.addEventListener('scroll', onScrollEnd, { once: true });
}

關鍵兼容性處理

問題解決方案
Mac 觸控板連續滾動觸發多次節流:setTimeout 或 requestAnimationFrame 鎖定 isScrolling
移動端無滾輪事件補充 touchstart/touchmove/touchend 手勢判斷上下滑動
鍵盤方向鍵/空格鍵導航監聽 keydown,映射 ArrowDown/Up、Space/Shift+Space 觸發同樣邏輯
無障礙訪問提供「禁用自定義滾動」開關,保留原生滾動條供輔助技術使用

生態庫推薦

  • fullPage.js:成熟全屏滾動庫,支援橫向/縱向、回調、響應式
  • ScrollMagic:滾動驅動動畫,可構建複雜敘事頁面
  • Locomotive Scroll:平滑滾動 + 視差效果,現代感強

性能優化建議

  • 使用 will-change: transform 提示瀏覽器優化
  • 避免在 wheel 監聽器中執行佈局觸發操作(offsetHeight 等)
  • 長頁面採用虛擬列表技術,非可視區塊卸載 DOM
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved