NextJS13 鼠标滚轮事件不适用于 Chrome 中的滚动转换

问题描述 投票:0回答:1

在我开始的全栈培训项目开始时,我感到无聊,并尝试实施我想到的想法。其中之一是创建具有单页应用程序 (SPA) 外观的主页。为此,我创建了一个可以实现滚动转换的组件,并且我希望该组件能够侦听键盘和鼠标滚轮事件以导航到上一个或下一个部分。鼠标滚轮事件在 Firefox 中完美运行,但在 Chrome 中不起作用。我通过在不同的地方添加 console.log 语句来研究它,我观察到正在检测到鼠标滚轮移动,但转换没有发生。你能帮我解决这个问题吗?我正在发送 Github 存储库链接和相关组件的代码。

我尝试过的:我创建了一个单页应用程序(SPA)组件,其滚动转换可监听键盘和鼠标滚轮事件。该组件根据键盘输入成功导航到上一个或下一个部分,并且它正确检测鼠标滚轮移动。

我的期望:我期望鼠标滚轮事件能够在 Chrome 中触发平滑的滚动过渡,类似于它们在 Firefox 中的工作方式。然而,在 Chrome 中,尽管检测到鼠标滚轮移动,但转换不起作用。我想了解为什么会发生这种行为并找到解决方案以使其按预期工作。

Github Repo.
Vercel Link

滚动组件:

import { useRef, useEffect, useState } from "react";

interface SectionData {
  name: string;
  className?: string;
  image?: string;
  title?: string;
  text?: string;
  textStyle?: string;
  children?: React.ReactNode;
}

const sectionsData: SectionData[] = [];

const Scroll = ({ sectionsData }: { sectionsData: SectionData[] }) => {
  const sectionRefs = sectionsData.map(() =>
    useRef<null | HTMLDivElement>(null)
  );
  const [currentSectionIndex, setCurrentSectionIndex] = useState<number>(0);

  const scrollToSection = (index: number) => {
    const ref = sectionRefs[index];
    if (ref.current) {
      ref.current.scrollIntoView({ behavior: "smooth" });
      setCurrentSectionIndex(index);
    }
  };

  useEffect(() => {
    const handleScroll = (event: { deltaY: number }) => {
      if (event.deltaY > 0) {
        if (currentSectionIndex < sectionsData.length - 1) {
          console.log("downed");
          scrollToSection(currentSectionIndex + 1);
        }
      } else {
        if (currentSectionIndex > 0) {
          console.log("upped");
          scrollToSection(currentSectionIndex - 1);
        }
      }
    };

    window.addEventListener("wheel", handleScroll);

    return () => {
      window.removeEventListener("wheel", handleScroll);
    };
  }, [currentSectionIndex]);

  return (
    <>
      {sectionsData.map((section, index) => (
        <section
          key={index}
          ref={sectionRefs[index]}
          className={`${section.className}`}
          style={{ backgroundImage: `url(${section.image})` }}
        >
          {section.title && <h1>{section.title}</h1>}
          {section.text && (
            <p className={`${section.textStyle}`}>{section.text}</p>
          )}
          {section.children}
          {index < sectionsData.length - 1 && (
            <div className="flex items-center justify-center h-screen">
              <div className="p-6 bg-amber-200 opacity-50 hover:opacity-100 transition-opacity rounded-lg shadow-lg">
                <button onClick={() => scrollToSection(index + 1)}>
                  Go to the {sectionsData[index + 1].name}
                </button>
              </div>
            </div>
          )}
        </section>
      ))}
    </>
  );
};
export default Scroll;

reactjs typescript scroll tailwind-css next.js13
1个回答
0
投票

我用scrollTo函数修复了它,但为什么这个工作其他函数不能,我不知道..

import { useRef, useEffect, useState, useContext, createContext } from "react";

interface SectionData {
  name: string;
  auto?: boolean;
  className?: string;
  image?: string;
  textStyle?: string;
  children?: React.ReactNode;
}

const ScrollContext = createContext({
  scrollToSection: (index: number) => {},
});

export const useScroll = () => useContext(ScrollContext);

const Scroll = ({ sectionsData }: { sectionsData: SectionData[] }) => {
  const sectionRefs = sectionsData.map(() =>
    useRef<null | HTMLDivElement>(null)
  );
  const [currentSectionIndex, setCurrentSectionIndex] = useState<number>(0);

  const scrollToSection = (index: number) => {
    const ref = sectionRefs[index];
    if (ref.current) {
      const top = ref.current.offsetTop;
      window.scrollTo({
        top,
        behavior: "smooth",
      });
      setCurrentSectionIndex(index);
    }
  };

  useEffect(() => {
    const handleScroll = (event: { deltaY: number }) => {
      if (event.deltaY > 0) {
        if (currentSectionIndex < sectionsData.length - 1) {
          scrollToSection(currentSectionIndex + 1);
        }
      } else {
        if (currentSectionIndex > 0) {
          scrollToSection(currentSectionIndex - 1);
        }
      }
    };

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "ArrowDown") {
        if (currentSectionIndex < sectionsData.length - 1) {
          scrollToSection(currentSectionIndex + 1);
        }
      } else if (event.key === "ArrowUp") {
        if (currentSectionIndex > 0) {
          scrollToSection(currentSectionIndex - 1);
        }
      }
    };

    window.addEventListener("wheel", handleScroll);
    window.addEventListener("keydown", handleKeyDown);

    return () => {
      window.removeEventListener("wheel", handleScroll);
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [currentSectionIndex]);
  return (
    <ScrollContext.Provider value={{ scrollToSection }}>
      <>
        {sectionsData.map((section, index) => (
          <section
            key={index}
            ref={sectionRefs[index]}
            className={`${section.className} ${
              section.auto !== undefined
                ? section.auto
                  ? "h-auto"
                  : "h-screen"
                : "h-screen"
            }`}
            style={{ backgroundImage: `url(${section.image})` }}
          >
            {section.children}
          </section>
        ))}
      </>
    </ScrollContext.Provider>
  );
};

export default Scroll;
© www.soinside.com 2019 - 2024. All rights reserved.