web-dev-qa-db-ja.com

スクロールとCSSスクロールスナップにキーボードイベントを同時に使用すると競合が発生する

を押すと、デモページを水平にスクロールできます Space Bar、 Page Up / Page Down そして Left Arrow / Right Arrow キー。マウスまたはトラックパッドでスナップスクロールすることもできます。

しかし、どちらか一方のみが機能します。

キーボードイベントとCSSスクロールスナップが共存できる方法はありますか?何が欠けていますか? 1週間以上この問題に取り組んできたので、どんな助けでも本当にありがたいです。


CodePenのデモを確認してください

(キーボードショートカットが機能しなくなったことを確認するために、スクロールスナップ効果を有効にするには、関連するCSSコードのコメントを解除してください。)


import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"

const sections = Array.from(document.querySelectorAll("section")).sort(
  (s1, s2) => {
    return s1.getBoundingClientRect().left - s2.getBoundingClientRect().left
  }
)

const getSectionInView = () => {
  const halfWidth = window.innerWidth / 2
  const index = sections.findIndex(
    section =>
      section.getBoundingClientRect().left <= halfWidth &&
      section.getBoundingClientRect().right > halfWidth
  )
  return index
}

const getNextSection = dir => {
  const sectionInViewIndex = getSectionInView()
  const nextIndex = sectionInViewIndex + dir
  const numSections = sections.length
  const nextSectionIndex =
    nextIndex < 0 || nextIndex >= numSections ? sectionInViewIndex : nextIndex
  return sections[nextSectionIndex]
}

const container = document.scrollingElement

const animateScroll = dir => {
  const from = container.scrollLeft
  const { left } = getNextSection(dir).getBoundingClientRect()
  return progress => (container.scrollLeft = from + progress * left)
}

window.onload = () => {
  document.body.onkeydown = event => {
    switch (event.key) {
      case " ": // Space Bar
      case "PageDown":
      case "ArrowRight": {      
        animate({
          easing: "out-quintic",
          change: animateScroll(1)
        })
        break
      }
      case "PageUp":
      case "ArrowLeft":  {      
        animate({
          easing: "out-quintic",
          change: animateScroll(-1)
        })
        break
      }
    }
  }
}

注:私は、スムーズなスクロールアニメーションを実現するために、 Animate Plus と呼ばれる小さくてエレガントなモジュールを使用しています。


更新:@KostjaのソリューションはChromeでは機能しますが、MacまたはiOSのSafariでは機能しません。私にとってSafariで機能することが重要です。

11
Tzar
window.onload = () => {
  window.addEventListener("wheel", () => {
    const direction = event.deltaY > 0 ? 1 : event.deltaY < 0 ? -1 : false;

    if (direction) {
      animate({
        easing: "out-quintic",
        change: animateScroll(direction)
      });
    }
  });

  document.body.onkeydown = event => {
    switch (event.key) {
      case " ": // Space Bar
      case "PageDown":
      case "ArrowRight": {
        animate({
          easing: "out-quintic",
          change: animateScroll(1)
        });
        break;
      }
      case "PageUp":
      case "ArrowLeft": {
        animate({
          easing: "out-quintic",
          change: animateScroll(-1)
        });
        break;
      }
    }
  };
};    

これはうまくいくはずです。

https://codepen.io/JZ6/pen/XWWQqRK

0
Jay Z