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;
        }
    }
}

 

posted @ 2024-07-11 11:18  Zion0707  阅读(77)  评论(0编辑  收藏  举报