实现鼠标滚轮放大缩小元素,鼠标移动带动元素移动从而调整元素位置

import { useState, useEffect, useRef, useCallback } from 'react';
import IMG from './assets/fans.png';

import style from './index.module.css';

const Home = () => {
    const [scale, setScale] = useState(1);
    const [position, setPosition] = useState({ x: 0, y: 0 });
    const [mousePosition, setMousePositon] = useState(null) as any;
    const [isDown, setIsDown] = useState(false);
    const divRef = useRef() as any;

    const onWheel = useCallback(
        (e) => {
            e.preventDefault(); // wheel要用js原生方法监听,并且使用此句,阻止外层有滚动条的元素滚动
            const { deltaY } = e;
            if (deltaY > 0) {
                const newScale = Math.min(scale * (1 + deltaY / 500), 10);
                setScale(newScale);
            }

            if (deltaY < 0) {
                const newScale = Math.max(scale * (1 - Math.abs(deltaY) / 500), 0.3);
                setScale(newScale);
            }
        },
        [scale],
    );

    useEffect(() => {
        const dom = document.getElementById('divRef');
        dom?.addEventListener('wheel', onWheel);

        return () => {
            dom?.removeEventListener('wheel', onWheel);
        };
    }, [onWheel]);

    const onMouseDown = useCallback((e) => {
        // e.preventDefault();
        // e.stopPropagation();
        setIsDown(true);
        const { clientX, clientY } = e;
        console.log('onMouseDown', clientX, clientY);
        setMousePositon({ clientX, clientY });
    }, []);

    const onMouseUp = useCallback((e) => {
        // e.preventDefault();
        // e.stopPropagation();
        console.log('onMouseUp', e);
        setIsDown(false);
        setMousePositon(null);
    }, []);

    const onMouseMove = useCallback(
        (e) => {
            // e.preventDefault();
            // e.stopPropagation();
            if (isDown) {
                // console.log('onMouseMove', e);
                const { clientX, clientY } = e;
                console.log('mousePosition', mousePosition);
                const moveX = clientX - mousePosition.clientX;
                const moveY = clientY - mousePosition.clientY;
                console.log('moveX', moveX, moveY);
                setMousePositon({ clientX, clientY });
                setPosition((pos) => {
                    const newPos = { x: pos.x + moveX, y: pos.y + moveY };
                    return newPos;
                });
            }
        },
        [isDown, mousePosition],
    );

    useEffect(() => {
        const dom = document.getElementById('divRef');
        dom?.addEventListener('onmousedown', onMouseDown);
        dom?.addEventListener('onmouseup', onMouseUp);
        dom?.addEventListener('onmousemove', onMouseMove);

        return () => {
            dom?.removeEventListener('onMouseDown', onMouseDown);
            dom?.removeEventListener('onmouseup', onMouseUp);
            dom?.removeEventListener('onmousemove', onMouseMove);
        };
    }, [onMouseDown, onMouseUp, onMouseMove]);

    return (
        <div className={style.Home}>
            <div className={style.test} ref={divRef} id="divRef" onMouseDown={onMouseDown} onMouseUp={onMouseUp} onMouseMove={onMouseMove}>
                <img
                    className={style.testImg}
                    src={IMG}
                    style={{
                        transformOrigin: '(50%, 50%)',
                        transform: `scale(${scale}) translate(${position.x / scale}px, ${position.y / scale}px)`,
                    }}
                    draggable={false}
                />
            </div>
            <div className={style.bottom}></div>
        </div>
    );
};

export default Home;

效果

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用 PySide6 中的 QGraphicsView 类可以实现鼠标滚轮放大缩小移动功能。具体实现步骤如下: 1. 继承 QGraphicsView 类创建自定义视图类,例如 MyGraphicsView。 ```python from PySide6.QtWidgets import QGraphicsView class MyGraphicsView(QGraphicsView): pass ``` 2. 在自定义视图类中重写 wheelEvent() 函数,实现鼠标滚轮缩放功能。可以通过调整视图的缩放比例和滚轮事件的 delta() 值来实现缩放效果。 ```python from PySide6.QtCore import Qt class MyGraphicsView(QGraphicsView): def wheelEvent(self, event): # 改变视图缩放比例 zoomInFactor = 1.25 zoomOutFactor = 1 / zoomInFactor if event.angleDelta().y() > 0: zoomFactor = zoomInFactor else: zoomFactor = zoomOutFactor self.scale(zoomFactor, zoomFactor) ``` 3. 在自定义视图类中添加 mousePressEvent() 和 mouseMoveEvent() 函数,实现鼠标移动功能。通过记录鼠标按下时的位置移动后的位置,计算出偏移量并调整视图的位置实现移动效果。 ```python class MyGraphicsView(QGraphicsView): def __init__(self, parent=None): super().__init__(parent) self.setDragMode(QGraphicsView.ScrollHandDrag) # 设置拖拽模式为滚动条拖拽 def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self._lastPos = event.pos() def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: delta = event.pos() - self._lastPos self._lastPos = event.pos() self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - delta.x()) self.verticalScrollBar().setValue(self.verticalScrollBar().value() - delta.y()) ``` 最终实现的 MyGraphicsView 类可以同时实现鼠标滚轮放大缩小移动功能。 完整代码如下: ```python from PySide6.QtWidgets import QGraphicsView from PySide6.QtCore import Qt class MyGraphicsView(QGraphicsView): def __init__(self, parent=None): super().__init__(parent) self.setDragMode(QGraphicsView.ScrollHandDrag) def wheelEvent(self, event): zoomInFactor = 1.25 zoomOutFactor = 1 / zoomInFactor if event.angleDelta().y() > 0: zoomFactor = zoomInFactor else: zoomFactor = zoomOutFactor self.scale(zoomFactor, zoomFactor) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self._lastPos = event.pos() def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: delta = event.pos() - self._lastPos self._lastPos = event.pos() self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - delta.x()) self.verticalScrollBar().setValue(self.verticalScrollBar().value() - delta.y()) ``` 可以在 PySide6 应用程序中使用 MyGraphicsView 类来创建带有鼠标滚轮放大缩小移动功能的视图。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊啊啊~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值