09-13-2012 03:43 PM - edited 09-14-2012 01:35 PM
Hey all, I just wanted to post a solution that i got via help from the dev community today. This code is to scale and rotate a control using the pinch gesture while simultaneously translating the X and Y position. The code is good for now and it works but it definitely needs some refining. Feel free to check out the code yourself (I believe you'll need a Dev Alpha for multi-touch handling) and give any feedback you have for improving the overall user experience ![]()
[Edit: updated code so that the final position of the object is remembered and loaded once touch interaction occurs again + added comments to describe code a bit better]
ImageView {
id: myImage
// This custom property stores the initial scale of the image when a
// pinch gesture begins
property double initialScale: 1.0
// This custom property determines how quickly the image grows or
// shrinks in response to the pinch gesture
property double scaleFactor: 1.0
//This is the initialization of two variables which will be used as the
//initial position measurement of the object
property int iniX: 0;
property int iniY: 0;
//Final X and Y position of object
property int finalX: 0;
property int finalY: 0;
layoutProperties: DockLayoutProperties {
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Center
}
//Set source of image
imageSource: "asset:///images/beer1.png"
gestureHandlers: [
// Add a handler for pinch gestures
PinchHandler {
// When the pinch gesture starts, save the initial scale of
// the image
onPinchStart: {
myImage.initialScale = myImage.scaleX;
}
// As the pinch expands or contracts, change the scale of the
// image
onPinchUpdate: {
myImage.scaleX = myImage.initialScale +
((event.pinchRatio - 1) * myImage.scaleFactor);
myImage.scaleY = myImage.initialScale +
((event.pinchRatio - 1) * myImage.scaleFactor);
myImage.rotationZ = event.rotation;
}
}
]
onTouch: {
if (event.isDown()) { // event.isDown() occurs once immediately when the user touches the object
//set initial X and Y position variables
iniX = event.windowX;
iniY = event.windowY;
} else if (event.isMove()) { //event.isMove() occurs as object is being dragged (presumably at 60Hz)
//calculate the translation by taking difference between initial position, final position and current position
myImage.translationX = event.windowX - iniX + finalX;
myImage.translationY = event.windowY - iniY + finalY;
} else if (event.isUp()) { //event.isUp() occurs once object is no longer touched by user
//set final position in variable to be loaded once the control (imageView) is touched by user again
finalX = myImage.translationX;
finalY = myImage.translationY;
}
}
}Cheers!
09-14-2012 08:43 AM
Thank you for sharing this code.
Regards
Graham
02-17-2013 08:31 PM - edited 02-18-2013 06:43 AM
I tried with your solution but found it unstable. I fixed the problem by means of flags that prevent interferences between the drag and pinch gestures. I also chose higher acceleration factors. [Edited to fix comments]
import bb.cascades 1.0
Page {
content: Container {
// The top-level container uses a dock layout so that the image can
// always remain centered on the screen as it changes size
layout: DockLayout {
}
ImageView {
id: myImage
// Flag to prevent a drag gesture from starting during pinch
property bool pinchHappening: false
// The scale of the image when a pinch gesture begins
property double initialScale: 1.0
// How fast the image grows/shrinks in response to the pinch gesture
property double scaleFactor: 1.25
// The rotation of the image when a pinch gesture begins
property double initialRotationZ: 0.0
// How fast the image rotates in response to the pinch gesture
property double rotationFactor: 1.5
// Flag to prevent dragging when a pinch ends but the two fingers are
// not taken off the screen simultaneously
property bool dragHappening: false
// The position of the image when a drag gesture begins
property double initialWindowX
property double initialWindowY
// How fast the image moves in response to the drag gesture
property double dragFactor: 1.25
// The image is initially centered on the container
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Center
imageSource: "asset:///images/picture1.png"
// Drag gesture
onTouch: {
// Determine the location inside the image that was touched,
// relative to the container, and move it accordingly
if (pinchHappening) {
// A pinch was started by touching the image with a second finger
// so interrupt any ongoing drag gesture
dragHappening = false
} else {
if (event.isDown()) {
// Start a dragging gesture
dragHappening = true
initialWindowX = event.windowX
initialWindowY = event.windowY
} else if (dragHappening && event.isMove()) {
// Move the image and record its new position
translationX += (event.windowX - initialWindowX) * dragFactor
translationY += (event.windowY - initialWindowY) * dragFactor
initialWindowX = event.windowX
initialWindowY = event.windowY
} else {
// Event type is Up or Cancel
// Interrupt any ongoing drag gesture
dragHappening = false
}
}
}
gestureHandlers: [
// Add a handler for pinch gestures
PinchHandler {
onPinchStarted: {
// Save the initial scale and rotation of the image
myImage.initialScale = myImage.scaleX
myImage.initialRotationZ = myImage.rotationZ
// Prevent a drag gesture from starting during pinch
myImage.pinchHappening = true
}
onPinchUpdated: {
// Rescale and rotate as the pinch expands/contracts/rotates
myImage.scaleX = myImage.initialScale + ((event.pinchRatio - 1) * myImage.scaleFactor)
myImage.scaleY = myImage.initialScale + ((event.pinchRatio - 1) * myImage.scaleFactor)
myImage.rotationZ = myImage.initialRotationZ + ((event.rotation) * myImage.rotationFactor)
}
onPinchEnded: {
// Allow a drag gesture to begin
myImage.pinchHappening = false
}
}
]
} // end of ImageView
} // end of Container
}// end of Page
02-17-2013 11:21 PM