web-dev-qa-db-fra.com

Conflit lors de l'utilisation simultanée d'événements de clavier pour le défilement et l'accrochage au défilement CSS

Vous pouvez faire défiler horizontalement ma page de démonstration en appuyant sur Space BarPage Up / Page Down et Left Arrow / Right Arrow clés. Vous pouvez également enclencher le défilement avec une souris ou un trackpad.

Mais seulement l'un ou l'autre fonctionne.

Existe-t-il un moyen de faire coexister les événements de clavier et l'alignement de défilement CSS? Qu'est-ce que je rate? Toute aide serait vraiment appréciée, car je lutte avec ce problème depuis plus d'une semaine.


Découvrez ma démo sur CodePen

(Veuillez décommenter la partie pertinente du code CSS pour activer l'effet de capture de défilement afin de voir que les raccourcis clavier cessent de fonctionner.)


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
      }
    }
  }
}

Remarque: J'utilise un petit module élégant appelé Animate Plus pour réaliser l'animation de défilement fluide.


Mise à jour: la solution de @ Kostja fonctionne dans Chrome, mais pas dans Safari pour Mac ou iOS, et il est crucial pour moi qu'elle fonctionne dans 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;
      }
    }
  };
};    

Cela devrait fonctionner.

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

0
Jay Z