Zoom at Mouse position



  • Hi all,
    I have a MouseArea as a child of Flickable and I want zoom an Image on the mouse position but I have always the same effect (zoom at x=0 y=0 position).

    Has anyone had the same problem?

    This is my sample qml code:

    import QtQuick 2.4
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width:1280
        height:800
    
        Rectangle {
            id:root
            anchors.fill: parent
    
            Flickable
            {
                id: flick
                anchors.fill: parent
                contentHeight: mapImage.height
                contentWidth: mapImage.width
                clip: true
    
                // Map Image
                Item {
                    id: mapImageContainer
                    width: Math.max(mapImage.width * mapImage.scale, flick.width)
                    height: Math.max(mapImage.height * mapImage.scale, flick.height)
    
                    Image
                    {
                        id: mapImage
                        z: dragArea.z+1
                        source: "http://www.astronomy2009.it/wp-content/uploads/2015/03/legge_hubble.jpg"
                        anchors.centerIn: parent
                        fillMode: Image.PreserveAspectFit
                    }
    
                    MouseArea {
                        id: dragArea
                        hoverEnabled: true
                        width: Math.max(mapImage.width * mapImage.scale, flick.width)
                        height: Math.max(mapImage.height * mapImage.scale, flick.height)
                        drag.target: mapImageContainer
                        drag.minimumX: 0
                        drag.minimumY: 0
                        drag.maximumX: flick.width - mapImage.width
                        drag.maximumY: flick.height - mapImage.height
                        onDoubleClicked: {
                            mapImage.scale = 1.0;
                            flick.contentHeight = mapImage.height * mapImage.scale
                            flick.contentWidth = mapImage.width * mapImage.scale
                        }
                        onWheel: {
                            if (wheel.modifiers & Qt.ControlModifier) {
                            } else {
                                var scale = mapImage.scale+mapImage.scale * wheel.angleDelta.y / 800;
                                mapImage.scale = scale;
                                flick.contentHeight = mapImage.height * mapImage.scale
                                flick.contentWidth = mapImage.width * mapImage.scale
                            }
                        }
                    }
                }
            }
        }
    }
    

    Regards
    Ivan

    Edited: Please put code after ``` (3 backticks) and end with the same - p3c0


  • Moderators

    @shedo
    Have a look at this blog post. It works nicely.

    Please use code tags ``` (3 backticks) while posting code. The list of supported tags are mentioned at the bottom of page.



  • Thanks a lot for your reply (It works perfectly) and sorry for my mistake in posting the code.

    I have only another question, I don't understand how compute the new dimension of the image or the rectangle (rect)... I have printed a console.debug of the scale or width and height... and they are always the same...


  • Moderators

    @shedo Can you post the updated code to get the clear picture ?



  • @p3c0

    Ok, no problem:

    import QtQuick 2.4
    import QtQuick.Window 2.2
    
    Window {
        id:mappanel
        visible: true
        width:1280
        height:800
        color: "white"
    
        Flickable
        {
            id: flick
            anchors.fill: parent
            clip: true
    
            // Map
            Rectangle {
                id: rect
                border.width: 2
                width: Math.max(mapImage.sourceSize.width, flick.width)
                height: Math.max(mapImage.sourceSize.height, flick.height)
                transform: Scale {
                    id: scaler
                    origin.x: pinchArea.m_x2
                    origin.y: pinchArea.m_y2
                    xScale: pinchArea.m_zoom2
                    yScale: pinchArea.m_zoom2
                }
    
                Image
                {
                    id: mapImage
                    z: dragArea.z+1
                    source: "http://www.astronomy2009.it/wp-content/uploads/2015/03/legge_hubble.jpg"
                    //anchors.centerIn: parent
                    //fillMode: Image.PreserveAspectFit
                    anchors.fill: parent
                }
    
                PinchArea {
                    id: pinchArea
                    anchors.fill: parent
                    property real m_x1: 0
                    property real m_y1: 0
                    property real m_y2: 0
                    property real m_x2: 0
                    property real m_zoom1: 0.5
                    property real m_zoom2: 0.5
                    property real m_max: 2
                    property real m_min: 0.5
    
                    onPinchStarted: {
                        console.log("Pinch Started")
                        m_x1 = scaler.origin.x
                        m_y1 = scaler.origin.y
                        m_x2 = pinch.startCenter.x
                        m_y2 = pinch.startCenter.y
                        rect.x = rect.x + (pinchArea.m_x1-pinchArea.m_x2)*(1-pinchArea.m_zoom1)
                        rect.y = rect.y + (pinchArea.m_y1-pinchArea.m_y2)*(1-pinchArea.m_zoom1)
                    }
                    onPinchUpdated: {
                        console.log("Pinch Updated")
                        m_zoom1 = scaler.xScale
                        var dz = pinch.scale-pinch.previousScale
                        var newZoom = m_zoom1+dz
                        if (newZoom <= m_max && newZoom >= m_min) {
                            m_zoom2 = newZoom
                        }
                    }
                    MouseArea {
                        id: dragArea
                        hoverEnabled: true
                        anchors.fill: parent
                        drag.target: rect
                        drag.filterChildren: true
    
                        onWheel: {
                            console.log("Wheel Scrolled")
                            pinchArea.m_x1 = scaler.origin.x
                            pinchArea.m_y1 = scaler.origin.y
                            pinchArea.m_zoom1 = scaler.xScale
                            pinchArea.m_x2 = mouseX
                            pinchArea.m_y2 = mouseY
    
                            var newZoom
                            if (wheel.angleDelta.y > 0) {
                                newZoom = pinchArea.m_zoom1+0.1
                                if (newZoom <= pinchArea.m_max) {
                                    pinchArea.m_zoom2 = newZoom
                                } else {
                                    pinchArea.m_zoom2 = pinchArea.m_max
                                }
                            } else {
                                newZoom = pinchArea.m_zoom1-0.1
                                if (newZoom >= pinchArea.m_min) {
                                    pinchArea.m_zoom2 = newZoom
                                } else {
                                    pinchArea.m_zoom2 = pinchArea.m_min
                                }
                            }
                            rect.x = rect.x + (pinchArea.m_x1-pinchArea.m_x2)*(1-pinchArea.m_zoom1)
                            rect.y = rect.y + (pinchArea.m_y1-pinchArea.m_y2)*(1-pinchArea.m_zoom1)
    
                            console.debug(rect.width+" -- "+rect.height+"--"+rect.scale)
    
                        }
                        MouseArea {
                            anchors.fill: parent
                            onClicked: console.log("Click in child")
                        }
                    }
                }
            }
        }
    }
    

    Basically I want to limit the drag of the image, in my old code I used this :

    drag.minimumX: 0
    drag.minimumY: 0
    drag.maximumX: flick.width - mapImage.width
    drag.maximumY: flick.height - mapImage.height
    

    But now it doesn't work

    Thanks for your help


  • Moderators

    @shedo try with sourceSize.

    drag.maximumX: flick.width - mapImage.sourceSize.width
    drag.maximumY: flick.height - mapImage.sourceSize.height
    


  • @p3c0 said:

    @shedo try with sourceSize.

    drag.maximumX: flick.width - mapImage.sourceSize.width
    drag.maximumY: flick.height - mapImage.sourceSize.height
    

    With this code, the image will not drag anymore, If you want you can try my old code and you can see the result I want to achieve (You try to move the image over the limits and it returns to the bounds automatically).


  • Moderators

    @shedo Hmm. Well then try to use the only relevant code from the blog post into your original code. The code of interest would be the one in onWheel handler and the properties it updates.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.