QML使用滚轮/触控板实现水平滚动/垂直滚动/缩放功能

引言

因为项目需要需要进行组件移动、缩放的开发,具体要求如下:

  1. 鼠标滚轮,实现垂直移动
  2. Ctrl+鼠标滚轮,实现缩放
  3. Alt+鼠标滚轮,实现水平移动
  4. 触控板移动,实现垂直、水平移动
  5. 触控板双指,实现缩放

在这里插入图片描述

核心代码

实现上述功能主要使用到两个组件MouseArea、PinchArea,MouseArea主要是进行鼠标事件的操作和部分触控板事件的操作,PinchArea主要是Mac下识别触控板的双指缩放。需要注意的是鼠标滚轮垂直移动和触控板垂直移动手势是混合在一起的,可以通过wheel.angleDelta.y是否为120的倍数去判断,如下所示:

	if (wheel.angleDelta.y && !(wheel.angleDelta.y % 120)) {
		// ...
	}
	else {
		// ...
	}

上述功能中需要识别Ctrl、Alt按键是否按下,需要通过wheel事件的modifiers 属性进行判断,如下所示:

MouseArea {
	onWheel: {
		if (wheel.modifiers & Qt.AltModifier) {
    		//..
		}
		else if (wheel.modifiers & Qt.ControlModifier) {
     		//..               
		}
		else {
			//..
		}
	}
}

完整代码

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    id: root
    width: 640
    height: 480
    visible: true

    //title: qsTr("Hello World")
    Rectangle {
        id: rect
        width: 100
        height: 100
        x: (parent.width - width) / 2
        y: (parent.height - height) / 2
        color: "blue"
    }

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    PinchArea {
        // Mac手势使用
        id: pinchArea
        anchors.fill: parent
        pinch.maximumScale: 20
        pinch.minimumScale: 0.2
    }

    Connections {
        target: mouseArea

        function onWheel(wheel) {
            if (wheel.pixelDelta === Qt.point(0, 0)
                    && wheel.angleDelta === Qt.point(0, 0)) {
                return
            }

            //console.log("wheel.angleDelta", wheel.angleDelta)
            //console.log("wheel.pixelDelta", wheel.pixelDelta)

            if (Qt.platform.os == "windows") {
                // Windows处理
                if (wheel.modifiers & Qt.AltModifier) {
                    // 左右滚动
                    if (wheel.angleDelta.x > 0) {
                        // 往左滚动
                        rect.x = Math.max(rect.x - 50, 0)
                    }
                    else {
                        // 往右滚动
                        rect.x = Math.min(rect.x + 50, root.width - rect.width)
                    }
                }
                else if (wheel.modifiers & Qt.ControlModifier) {
                    // 缩放
                    if (wheel.angleDelta.y > 0) {
                        rect.scale = Math.min(rect.scale + 0.1, 2)
                    }
                    else {
                        rect.scale = Math.max(rect.scale - 0.1, 1)
                    }
                }
                else {
                    if (wheel.angleDelta.y && !(wheel.angleDelta.y % 120)) {
                        // 鼠标滚动
                        if (wheel.angleDelta.y > 0) {
                            // 向上滚动
                            rect.y = Math.max(rect.y - 50, 0)
                        }
                        else {
                            // 向下滚动
                            rect.y = Math.min(rect.y + 50, root.height - rect.height)
                        }
                    }
                    else {
                        // 触摸板滚动
                        let tempX = rect.x - wheel.angleDelta.x
                        tempX = Math.max(tempX, 0)
                        tempX = Math.min(tempX, root.width - rect.width)
                        rect.x = tempX

                        let tempY = rect.y + wheel.angleDelta.y
                        tempY = Math.max(tempY, 0)
                        tempY = Math.min(tempY, root.height - rect.height)
                        rect.y = tempY
                    }
                }
            }
            else {
                // Mac处理
                if (wheel.modifiers & Qt.AltModifier) {
                    // 左右滚动
                    if (wheel.angleDelta.y > 0) {
                        // 往左滚动
                        rect.x = Math.max(rect.x - 50, 0)
                    }
                    else {
                        // 往右滚动
                        rect.x = Math.min(rect.x + 50, root.width - rect.width)
                    }
                }
                else if (wheel.modifiers & Qt.ControlModifier) {
                    // 缩放
                    if (wheel.angleDelta.y > 0) {
                        rect.scale = Math.min(rect.scale + 0.1, 2)
                    }
                    else {
                        rect.scale = Math.max(rect.scale - 0.1, 1)
                    }
                }
                else {
                    if (wheel.angleDelta.y && !(wheel.angleDelta.y % 120)) {
                        // 鼠标滚动
                        if (wheel.angleDelta.y > 0) {
                            // 向上滚动
                            rect.y = Math.max(rect.y - 50, 0)
                        }
                        else {
                            // 向下滚动
                            rect.y = Math.min(rect.y + 50, root.height - rect.height)
                        }
                    }
                    else {
                        // 触摸板滚动
                        let tempX = rect.x + wheel.pixelDelta.x
                        tempX = Math.max(tempX, 0)
                        tempX = Math.min(tempX, root.width - rect.width)
                        rect.x = tempX

                        let tempY = rect.y + wheel.pixelDelta.y
                        tempY = Math.max(tempY, 0)
                        tempY = Math.min(tempY, root.height - rect.height)
                        rect.y = tempY
                    }
                }
            }
        }
    }

    Connections {
        target: pinchArea

        property double oriScale: 1

        function onPinchStarted(pinch) {
            oriScale = rect.scale
        }

        function onPinchUpdated(pinch) {
            let tempScale = pinch.scale * oriScale
            tempScale = Math.min(tempScale, 2)
            tempScale = Math.max(tempScale, 1)
            rect.scale = tempScale
        }

        //function onPinchFinished(pinch) {
        //    rect.scale = pinch.scale * oriScale
        //    console.log("onPinchFinished", pinch.scale)
        //}
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Arui丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值