2
votes

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.

1
Set the arbitrary transform origin point to some constants to get a feel for how these values act.Kuba hasn't forgotten Monica
Thanks for the suggestion, I tried that, it seems to have no effect, ``` transform: Scale {origin.x: 100; origin.y: 100;} ``` Seems to do nothingEdwin Fernandez
Try without the flickable. Just Item and within it an Image with a transform, nothing else.Kuba hasn't forgotten Monica

1 Answers

-1
votes

For posterity, 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