react hooks实现对元素拖拽及鼠标滚轮缩放
hooks.js
import { useCallback, useState } from 'react';
// 拖拽
export function useDrag() {
const [isDragging, setIsDragging] = useState(false);
const [initialPosition, setInitialPosition] = useState({ x: 0, y: 0 });
const [initialMousePosition, setInitialMousePosition] = useState({ x: 0, y: 0 });
const handleMouseDown = useCallback((e) => {
setIsDragging(true);
setInitialMousePosition({ x: e.clientX, y: e.clientY });
setInitialPosition({ x: e.currentTarget.offsetLeft, y: e.currentTarget.offsetTop });
}, []);
const handleMouseMove = useCallback(
(e) => {
if (isDragging) {
const dx = e.clientX - initialMousePosition.x;
const dy = e.clientY - initialMousePosition.y;
e.currentTarget.style.left = `${initialPosition.x + dx}px`;
e.currentTarget.style.top = `${initialPosition.y + dy}px`;
}
},
[isDragging, initialMousePosition, initialPosition]
);
const handleMouseUp = useCallback(() => {
setIsDragging(false);
}, []);
return {
handleMouseDown,
handleMouseMove,
handleMouseUp,
};
}
// 缩放
export function useZoom(initialScale = 1) {
const [scale, setScale] = useState(initialScale);
const handleWheel = useCallback(
(e) => {
if (e.deltaY !== 0) {
const newScale = scale + (e.deltaY > 0 ? -0.05 : 0.05);
setScale(newScale < 0.5 ? 0.5 : newScale); // 防止缩放过小
e.currentTarget.style.transform = `scale(${newScale})`;
}
},
[scale]
);
return {
handleWheel,
scale,
};
}
page.jsx
import './index.less'; import { useDrag, useZoom } from './hooks'; const DragZoom = () => { const { handleMouseDown, handleMouseMove, handleMouseUp } = useDrag(); const { handleWheel, scale } = useZoom(); return ( <div className="drag-zoom"> <div className="area"> <div onMouseDown={handleMouseDown} onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} onWheel={handleWheel} className="element" style={{ transform: `scale(${scale})`, }} /> </div> </div> ); }; export default DragZoom;
index.less
.drag-zoom { width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; .area { width: 500px; height: 500px; border: 1px solid #ddd; position: relative; overflow: hidden; .react-draggable { border: 1px solid goldenrod; } .element { position: absolute; width: 100px; height: 100px; cursor: grab; transition: transform 0.3s ease; background: paleturquoise; } } }