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
