zoom in/out a canvas on center
-
I'm trying to do an app where I can add some points around an image. I have done the basic, load an image and add a canvas. When press the space key I set the canvas position.
I want the canvas to be always the same size when I resize the image. My problem is that my canvas doesn't look to be on the correct position when zoom in/zoom out. It looks like I'm doing some mistake and not move it around the center.
zooming in v
vice-versa
zooming out v
import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Window 2.1 Rectangle { width: 500 height: 500 color: "gray" Flickable { id: flick anchors.fill: parent contentWidth: 500 contentHeight: 500 PinchArea { width: Math.max(flick.contentWidth, flick.width) height: Math.max(flick.contentHeight, flick.height) property real initialWidth property real initialHeight property real initialTesteX property real initialTesteY onPinchStarted: { initialWidth = flick.contentWidth initialHeight = flick.contentHeight initialTesteX = marker.canvasX initialTesteY = marker.canvasY } onPinchUpdated: { // adjust content pos due to drag flick.contentX += pinch.previousCenter.x - pinch.center.x flick.contentY += pinch.previousCenter.y - pinch.center.y // resize content flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center) marker.canvasX = initialTesteX*(pinch.scale) marker.canvasY = initialTesteY*(pinch.scale) } onPinchFinished: { // Move its content within bounds. flick.returnToBounds() } Canvas { id: marker anchors { top: parent.top left: parent.left margins: 4 } z: 100 property real canvasX: 341 property real canvasY: 330 width: flick.contentWidth height: flick.contentHeight antialiasing: true transformOrigin: Item.TopLeft onPaint: { var ctx = getContext( "2d" ); ctx.save(); ctx.clearRect( 0, 0, width, height ); ctx.lineWidth = 2; ctx.beginPath(); ctx.strokeStyle = "blue" ctx.arc(canvasX, canvasY, 6, 0, Math.PI * 2 ); ctx.stroke(); ctx.restore(); } } Rectangle { id: image width: flick.contentWidth height: flick.contentHeight color: "white" Image { anchors.fill: parent source: "grid.png" MouseArea { focus: true hoverEnabled: true Keys.onPressed: { if ( event.key === Qt.Key_Space ) { console.log("Space"); marker.canvasX = mouseX-6 marker.canvasY = mouseY-6 console.log(mouseX) console.log(mouseY) marker.requestPaint() event.accepted = true } } anchors.fill: parent onDoubleClicked: { //flick.contentWidth = 500 //flick.contentHeight = 500 //marker.canvasX = 341 //marker.canvasY = 330 } onClicked: { //marker.canvasX = mouseX-6 //marker.canvasY = mouseY-6 //marker.requestPaint() console.log(mouseX) console.log(mouseY) } onPositionChanged: { console.log(mouseX) console.log(mouseY) } } } } } } }
Can you guide me on how to do this the right way?
-
I'm no QML guru (or even a proper user) but this one I find rather dubious:
flick.contentX += pinch.previousCenter.x - pinch.center.x flick.contentY += pinch.previousCenter.y - pinch.center.y
Can you reduce the number of additions (and subtractions)? You're probably accumulating a mighty floating point error here by just getting the offset and moving the content by small additions. If not, at least use an algorithm that's more numerically stable than this, e.g. kahan summation.
PS
You could also take a peek here for some more considerationsPS 2
Also additional thing to consider is catastrophic cancellation in the subtraction, albeit it shouldn't happen. So one can as first step rephrase the expressions like:previousCenters += pinch.previousCenter.x centers += pinch.center.x flick.contentX = previousCenters - centers // Only here do the subtraction
And additionally look up for the treatment of the actual summing.