同步滚动反应。 div 主卷轴方块 window

Sync scroll react. div block with main scroll on window

我想同步 div 滚动条和正文滚动条。

我尝试了一些带有两个 div 的示例,但我无法通过主体滚动修复它。

带有两个 div 的示例代码:https://codesandbox.io/s/react-custom-scroll-sync-of-2-divs-10xpi

我的代码

https://codesandbox.io/s/funny-rain-ditbv

import "./styles.css";
import { useRef } from "react";

export default function App() {
  const firstDivRef = useRef();
  const secondDivRef = useRef();

  const handleScrollFirst = (scroll) => {
    secondDivRef.current.scrollTop = scroll.target.scrollTop;
  };

  const handleScrollSecond = (scroll) => {
    firstDivRef.current.scrollTop = scroll.target.scrollTop;
  };

  return (
    <div
      className="App"
      style={{
        display: "flex",
   
   
    
      }}
    >
      <div
        onScroll={handleScrollFirst}
        ref={firstDivRef}
        style={{
          height: "500px",
          overflow: "scroll",
          backgroundColor: "#FFDAB9",
          position: "sticky",
          top: "0px"
        }}
      >
        <div style={{ height: 5000, width: 300 }}>
          The first div (or it can be tbody of a table and etc.)
          {[...new Array(1000)].map((_, index) => {
            const isEven = index % 2 === 0;
            return (
              <div style={{ backgroundColor: isEven ? "#FFFFE0  " : "#FFDAB9" }}>
                {index}
              </div>
            );
          })}
        </div>
      </div>

      <div
        onScroll={handleScrollSecond}
        ref={secondDivRef}
        style={{
          height: "100%",

          backgroundColor: "#EEE8AA"
        }}
      >
        <div style={{ height: 5000, width: 200 }}>
          The second div
          {[...new Array(1000)].map((_, index) => {
            const isEven = index % 2 === 0;
            return (
              <div style={{ backgroundColor: isEven ? "#FFFFE0  " : "#FFDAB9" }}>
                {index}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

试试下一个例子。这是一个快速草图,但也许它会对你有所帮助。

https://codesandbox.io/s/gallant-goldwasser-19g4d?file=/src/App.js

使用不同的 div 比使用 div 和 window 更容易。

但最终设法 运行 它带有 div 和正文。

诀窍是他们互相阻止,因为他们听取了彼此的价值观。


import "./styles.css";
import { useEffect, useRef, useState } from "react";

export default function App() {
  const firstDivRef = useRef();

  const [scrollTop, setScrollTop] = useState(0);
  const [disableBodyScroll, setDisableBodyScroll] = useState(false);
  const handleScrollFirst = (scroll) => {
    setScrollTop(scroll.target.scrollTop);
  };

  useEffect(() => {
    if (firstDivRef.current && !disableBodyScroll) {
      firstDivRef.current.scrollTop = scrollTop;
    }
    if (disableBodyScroll) {
      window.scrollTo(0, scrollTop);
    }
  }, [firstDivRef, scrollTop, disableBodyScroll]);

  useEffect(() => {
    const onScroll = () => {
      console.log(disableBodyScroll, window.scrollY);

      if (!disableBodyScroll) {
        setScrollTop(window.scrollY);
      }
    };
    // clean up code
    window.removeEventListener("scroll", onScroll);
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, [disableBodyScroll]);

  return (
    <div
      className="App"
      style={{
        display: "flex"
      }}
    >
      <div
        onMouseEnter={() => setDisableBodyScroll(true)}
        onMouseLeave={() => setDisableBodyScroll(false)}
        onScroll={handleScrollFirst}
        ref={firstDivRef}
        style={{
          height: "500px",
          overflow: "scroll",
          backgroundColor: "#FFDAB9",
          position: "sticky",
          top: "0px"
        }}
      >
        <div style={{ height: 5000, width: 300 }}>
          The first div (or it can be tbody of a table and etc.)
          {[...new Array(1000)].map((_, index) => {
            const isEven = index % 2 === 0;
            return (
              <div style={{ backgroundColor: isEven ? "#FFFFE0  " : "#FFDAB9" }}>
                {index}
              </div>
            );
          })}
        </div>
      </div>

      <div
        style={{
          height: "100%",

          backgroundColor: "#EEE8AA"
        }}
      >
        <div style={{ height: 5000, width: 200 }}>
          The second div
          {[...new Array(1000)].map((_, index) => {
            const isEven = index % 2 === 0;
            return (
              <div style={{ backgroundColor: isEven ? "#FFFFE0  " : "#FFDAB9" }}>
                {index}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

https://codesandbox.io/s/ancient-dream-tzuel?file=/src/App.js