使用垂直鼠标滚轮在React组件上水平滚动

时间:2019-05-15 16:24:14

标签: javascript reactjs scroll horizontal-scrolling mousewheel

我有一个组件,当在较小的桌面窗口中时,该组件可以调整为水平的引导卡行。对于没有水平鼠标滚轮并且不使用触摸板的用户,我希望允许用户将鼠标悬停在此特定组件上时使用其垂直鼠标滚轮移动来水平滚动。

这是我原来基于以下代码的StackOverflow问题: https://stackoverflow.com/a/15343916/8387497

Horizo​​ntal Scroll helper组件:

function horizontalScroll (event) {
  const delta = Math.max(-1, Math.min(1, (event.nativeEvent.wheelDelta || -event.nativeEvent.detail)))
  event.currentTarget.scrollLeft -= (delta * 10)
  event.preventDefault
}

我如何在需要水平滚动的组件上实现它:

<Row className='announcements-home' onWheel={horizontalScroll} >

将这个horizontalScroll帮助函数放置在React onWheel事件中后,它将水平和垂直滚动。我想要的结果只是水平滚动。此外,Firefox似乎完全不响应这些更改对水平滚动进行响应。

3 个答案:

答案 0 :(得分:4)

好的,所以问题似乎在于,您仅引用功能event.preventDefault,而不是调用它。 在末尾添加一些括号以调用该方法: event.preventDefault()

但是我在寻找一些简单的代码时发现了这个问题,因此如果其他人处于相同的情况下,我也会为此留下钩子

import { useRef, useEffect } from "react";

export function useHorizontalScroll() {
  const elRef = useRef();
  useEffect(() => {
    const el = elRef.current;
    if (el) {
      const onWheel = e => {
        e.preventDefault();
        el.scrollTo({
          left: el.scrollLeft + e.deltaY,
          behavior: "smooth"
        });
      };
      el.addEventListener("wheel", onWheel);
      return () => el.removeEventListener("wheel", onWheel);
    }
  }, []);
  return elRef;
}

用法:

import React from "react";
import { useSideScroll } from "./useSideScroll";

export const SideScrollTest = () => {
  const scrollRef = useHorizontalScroll();
  return (
    <div ref={scrollRef} style={{ width: 300, overflow: "auto" }}>
      <div style={{ whiteSpace: "nowrap" }}>
        I will definitely overflow due to the small width of my parent container
      </div>
    </div>
  );
};

答案 1 :(得分:1)

onWheel = (e) => {
    e.preventDefault()
    var container = document.getElementById('container')
    var containerScrollPosition = document.getElementById('container').scrollLeft
    container.scrollTo({
        top: 0,
        left: largeContainerScrollPosition + e.deltaY
        behaviour: 'smooth' //if you want smooth scrolling
    })
}

答案 2 :(得分:1)

TarVK 提出的钩子还有一个小问题。一旦你滚动到最后并继续滚动,当我们习惯于包含开始滚动的元素时,什么也不会发生。所以我做了一个修复:

export function useHorizontalScroll () {
  const elRef = useRef();
  useEffect(() => {
    const el = elRef.current;
    if (el) {
      const onWheel = (e) => {
        if (e.deltaY === 0) return;
        if (
          !(el.scrollLeft === 0 && e.deltaY < 0) &&
          !(el.scrollWidth - el.clientWidth - Math.round(el.scrollLeft) === 0 && 
              e.deltaY > 0)
        ) {
          e.preventDefault();
        }
        el.scrollTo({
          left: el.scrollLeft + e.deltaY,
          behavior: 'smooth'
        });
      };
      el.addEventListener('wheel', onWheel);
      return () => el.removeEventListener('wheel', onWheel);
    }
  }, []);
  return elRef;
}

只有当有空间可以在那个方向滚动时,它才会有条件地阻止默认行为,所以当没有空间可以滚动时,例如整个页面将开始滚动。变化在这里:

        if (
          !(el.scrollLeft === 0 && e.deltaY < 0) &&
          !(el.scrollWidth - el.clientWidth - Math.round(el.scrollLeft) === 0 && 
              e.deltaY > 0)
        ) {
          e.preventDefault();
        }