ค้นหาเว็บไซต์

reactjs - คลิกและลากเพื่อเลื่อนด้วยเมาส์, คอมโพเนนต์ React Typescript


ฉันกำลังพยายามสร้างคอมโพเนนต์ React ที่สามารถนำกลับมาใช้ใหม่ได้ ซึ่งจะช่วยให้ฉันสามารถเลื่อนแนวนอนด้วยเมาส์โดยการคลิกและลากไปทางซ้ายและขวา เหมือนกับที่คุณทำกับทัชแพดหรือหน้าจอสัมผัสใด ๆ

พฤติกรรมที่คาดไว้: Div ควรเลื่อนขวาและซ้ายตามการลากเมาส์

พฤติกรรมที่ได้: การคลิกและลากไม่เลื่อนหน้า แต่การเอาเมาส์ไปวางเหนือ Div ที่อ้างอิงแล้วเคลื่อนมันไปด้านข้างจะทำให้ div เลื่อนบางส่วนได้

ฉันลองไอเดียหลายอย่างแล้ว แต่ฉันก็ยังทำให้มันใช้งานได้ไม่ได้

ฉันได้ลองหลายวิธีในการทำให้มันทำงาน... พยายามปรับแต่งตัวเลื่อน (ดูเหมือนไม่สามารถทำได้) ทั้งมีและไม่มี eventListeners... แต่โดยรวมแล้วฉันคงพูดได้ว่าโค้ดของฉันสามารถทำงานได้โดยมีการปรับปรุงบ้าง

ฉันกำลังพยายามปรับตัวอย่างที่ใช้งานได้นี้ให้กับคอมโพเนนต์ React ของฉัน: ตัวอย่างที่ใช้งานได้แต่ไม่สามารถใช้กับ React

ฉันกำลังสร้างคอมโพเนนต์ Draggable ที่จะห่อ div ใดๆ จากแอปที่มีการล้นในแนวนอนจากมุมมอง ตรรกะในการกำหนดเป้าหมาย div ลูกจาก Draggable ใช้ได้ดี (ใช้ useRef)

นี่คือโค้ดเพนที่ทำซ้ำสิ่งที่ฉันทำอยู่: โค้ดเพนพร้อมโค้ดของฉัน

นี่คือส่วนประกอบของฉัน:

import React, { useState, ReactNode, useRef, RefObject, useEffect } from "react";

type DraggableProps = {
  innerRef: RefObject<HTMLDivElement>;
  rootClass: string;
  children: ReactNode;
};

export const Draggable = ({ innerRef, rootClass = "", children }: DraggableProps) => {
  const slider = innerRef.current as HTMLElement;
  const ourRef = useRef<HTMLDivElement>(null);
  const [pageX, setPageX] = useState(0);
  const [scrollX, setScrollX] = useState(0);
  const [isScrolling, setIsScrolling] = useState(false);

  useEffect(() => {
    handleMouseDown()
  },[isScrolling])

  const handleMouseDown = () => {
      setIsScrolling(true);
    slider?.addEventListener("mousedown", (e) => {
      console.log("Mouse down => event", e);
      setPageX(e.pageX - slider.offsetLeft);
      setScrollX(slider?.scrollLeft);
    });
    slider?.addEventListener("mouseleave", () => {
      console.log("Mouse leave");
      slider.removeEventListener("mousedown", () => {console.log("remove mouse down");
      });
      slider.removeEventListener("mousemove", () => {console.log("remove mouse move");
      });
      setIsScrolling(false);
    });
    slider?.addEventListener("mouseup", () => {
      console.log("Mouse up");
      slider.removeEventListener("mousedown", () => {console.log("remove mouse down");
      });
      slider.removeEventListener("mousemove", () => {console.log("remove mouse move");
      });
      setIsScrolling(false);
    });
    slider?.addEventListener("mousemove", (e) => {
      if (!isScrolling) return;
      e.preventDefault();
      console.log("Mouse move => pageX", pageX);

      const x = e.pageX - slider?.offsetLeft;
      const walk = x - pageX;
      slider.scrollLeft = scrollX - walk;
    });  
  };

  return (
    <div ref={ourRef} onMouseDown={handleMouseDown} className={rootClass}>
      {children}
    </div>
  );
};

คำตอบ #1

const Draggable = ({rootClass = "", children }) => {
  const ourRef = useRef(null);
    const [isMouseDown, setIsMouseDown] = useState(false);
    const mouseCoords = useRef({
        startX: 0,
        startY: 0,
        scrollLeft: 0,
        scrollTop: 0
    });
  const [isScrolling, setIsScrolling] = useState(false);
    const handleDragStart = (e) => {
        if (!ourRef.current) return
      const slider = ourRef.current.children[0];
        const startX = e.pageX - slider.offsetLeft;
        const startY = e.pageY - slider.offsetTop;
        const scrollLeft = slider.scrollLeft;
        const scrollTop = slider.scrollTop;
        mouseCoords.current = { startX, startY, scrollLeft, scrollTop }
        setIsMouseDown(true)
        document.body.style.cursor = "grabbing"
    }
    const handleDragEnd = () => {
        setIsMouseDown(false)
        if (!ourRef.current) return
        document.body.style.cursor = "default"
    }
    const handleDrag = (e) => {
        if (!isMouseDown || ! ourRef.current) return;
        e.preventDefault();
        const slider = ourRef.current.children[0];
        const x = e.pageX - slider.offsetLeft;
        const y = e.pageY - slider.offsetTop;
        const walkX = (x - mouseCoords.current.startX) * 1.5;
        const walkY = (y - mouseCoords.current.startY) * 1.5;
        slider.scrollLeft = mouseCoords.current.scrollLeft - walkX;
        slider.scrollTop = mouseCoords.current.scrollTop - walkY;
        console.log(walkX, walkY)
    }

  return (
    <div ref={ourRef} onMouseDown={handleDragStart} onMouseUp={handleDragEnd} onMouseMove={handleDrag} className={rootClass + "flex overflow-x-scroll"}>
      {children}
    </div>
  );
};

ฉันได้ปรับโค้ดของคุณให้เป็นเวอร์ชันที่ใช้งานได้ซึ่งคุณสามารถดูได้ที่นี่ https://codepen.io/sandstone991/pen/vYzvZNa

บทความที่เกี่ยวข้อง