Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. PinchArea default behavior does not respect the pinch center + solution
Forum Updated to NodeBB v4.3 + New Features

PinchArea default behavior does not respect the pinch center + solution

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
qml pincharea
1 Posts 1 Posters 219 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • pieterbekaertP Offline
    pieterbekaertP Offline
    pieterbekaert
    wrote on last edited by
    #1

    [With Qt 5.15.2:]
    When using the default PinchArea behavior by setting pinch.target, the center of the pinch movement is ignored for zooming in or out. Zooming happens with respect to the center of the target.
    This can be observed by running below example code and zooming in/out near the border of the area. In certain scenarios, this can even cause the target to go out of reach: zoom in strongly to e.g. the upperleft corner, and the zoom out significantly. The target shrinks to the bottom right and disappears.

    import QtQuick 2.0
    
    Item {
    
        Rectangle {
            id:thetarget
            width: parent.width
            height:parent.height
            color: "red"
            border.color:"blue"
            border.width: 5
    
            Text {
                width: parent.width
                height: parent.height
                text: "FOO\nBAR";
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
                font.pixelSize: 200
            }
        }
        PinchArea {
            id: pinchArea
            anchors.fill: parent
            pinch.target: thetarget 
            pinch.minimumRotation: 0
            pinch.maximumRotation: 0
            pinch.maximumScale: 10
            pinch.minimumScale:1
            pinch.minimumX: -width * thetarget.scale
            pinch.maximumX: width * thetarget.scale
            pinch.minimumY: -height * thetarget.scale
            pinch.maximumY: height * thetarget.scale
            pinch.dragAxis: Pinch.XAndYAxis
    }
    

    I worked out a solution:

    • remove the line setting the pinch.target

    • configure a handler for pinch updates by adding below fragment to the PinchArea:

            onPinchUpdated: function(pinchEvent) {
                // scale change:
                var oldScale = thetarget.scale;
                var newScale = oldScale * (pinchEvent.scale / pinchEvent.previousScale);
                newScale = Math.min(
                            Math.max(pinchArea.pinch.minimumScale, newScale),
                            pinchArea.pinch.maximumScale);
                var scaleRatio = newScale / oldScale;
                thetarget.scale = newScale;
    
                // keep the map center point on its place:
                thetarget.x *= scaleRatio;
                thetarget.y *= scaleRatio;
    
                // compensate to keep old pinch center in place:
                var deltaX = pinchEvent.previousCenter.x - thetarget.width/2; // positive if pinching right of center
                var deltaY = pinchEvent.previousCenter.y - thetarget.height/2; // positive if pinching below center
                deltaX *= (newScale - oldScale)/newScale; //positive a.o. if pinch center is to the right and zooming in
                deltaY *= (newScale - oldScale)/newScale;
                thetarget.x -= deltaX;
                thetarget.y -= deltaY;
    
                // apply the move of the pinch center:
                deltaX = pinchEvent.center.x - pinchEvent.previousCenter.x; // positive if panning to the right
                deltaY = pinchEvent.center.y - pinchEvent.previousCenter.y
                thetarget.x += deltaX;
                thetarget.y += deltaY;
    
                // enforce limits:
                thetarget.x = Math.min(Math.max(thetarget.x, pinchArea.pinch.minimumX), 
                                                pinchArea.pinch.maximumX);
                thetarget.y = Math.min(Math.max(thetarget.y, pinchArea.pinch.minimumY), 
                                                pinchArea.pinch.maximumY);
            }
    

    Notice that it is important not to put the PinchArea element inside the target element: this would impact the coordinates used in the pinchEvent and invalidates the above calculation.

    IMO the current implementation is a bug, but I did not find a ticket in the Qt bug tracker. Not sure if I should/can report an issue...

    1 Reply Last reply
    0

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved