qtqmlqt5qtquick2qtquickcontrols2

Zooming/Scaling an Image at a specific point within a Flickable


By moving a Slider, I want to be able to scale (zoom in) on an Image and once scaled (zoomed in), be able to move around, ( flick ) I have this example working here below, but my problem is the following.

If I zoom in, scale in, and then flick around to a spot on the image, then I want to zoom (scale) in further on that specific point in the center of the window, when I scale in using the Slider, the zoom (scale) occurs at the center of the image because by default the 'transformOrigin' is Item.Center

Try running the code to understand what I am talking about: ( you will need to change the image source)

import QtQuick 2.12
import QtQuick.Controls 2.3


Item {
    id: mainId
    width: 1280
    height: 720
    property int scaleMultiplier: 3


    Flickable {
        id: flickArea
        anchors.fill: parent
        focus: true
        contentWidth: Math.max(inner.width * slider.value * scaleMultiplier, width)
        contentHeight: Math.max(inner.height  * slider.value * scaleMultiplier, height)
        anchors.centerIn: parent
        boundsBehavior: Flickable.StopAtBounds
        contentX: contentWidth === width ? 0 : inner.width * slider.value * scaleMultiplier / 2 - flickArea.width / 2
        contentY: contentHeight === height ? 0 : inner.height * slider.value * scaleMultiplier / 2 - flickArea.height / 2


        Image {
            id: inner
            scale: slider.value * scaleMultiplier
            anchors.centerIn: parent
            source: "test_images/1.png"
        }
    }

    Slider {
        id: slider
        value: .01
        orientation: Qt.Vertical
        anchors {
            bottom: parent.bottom
            right: parent.right
            top: parent.top
            margins: 50
        }

        from: 0.01
    }

}

I tried setting an arbitrary transform origin point like so:

Image {
            id: inner
            scale: slider.value * scaleMultiplier
            anchors.centerIn: parent

            source: "test_images/1.png"

            transform: Scale {
                                id: scaleID ;
                                origin.x: flickArea.contentX + flickArea.width * flickArea.visibleArea.widthRatio / 2
                                origin.y: flickArea.contentY + flickArea.height * flickArea.visibleArea.heightRatio / 2
            }
        }

But it seems to have no effect. Any help is appreciated. What am I missing?

Again what I want is when I flick to a specific point on the Image, and scale in, I want the point of origin to scale into be the area in the center of the viewable flickarea. For example let's say I am zoomed in the upper right corner of the image, then I wish to zoom in further, when I zoom in further, the Image is brought back to the center of the image.

Thanks.


Solution

  • Found the answer with help from @sierdzio here:

    https://forum.qt.io/topic/105233/zooming-scaling-an-image-at-a-specific-point-within-a-flickable/2

    I needed to use resizeContents() method from Flickable

    property real zoom: 1;
    onZoomChanged: {
            var zoomPoint = Qt.point(flickArea.width/2 + flickArea.contentX,
                                 flickArea.height/2 + flickArea.contentY);
    
            flickArea.resizeContent((inner.width * zoom), (inner.height * zoom), zoomPoint);
            flickArea.returnToBounds();
        }
    

    and

    // REMOVE THESE LINES:
    contentWidth: Math.max(inner.width * slider.value * scaleMultiplier, width)
    contentHeight: Math.max(inner.height  * slider.value * scaleMultiplier, height)
    contentX: contentWidth === width ? 0 : inner.width * slider.value * scaleMultiplier / 2 - flickArea.width / 2
    contentY: contentHeight === height ? 0 : inner.height * slider.value * scaleMultiplier / 2 - flickArea.height / 2
    
    // Instead, do:
    contentWidth: inner.width
    contentHeight: inner.height