I'm building an iPhone app. I have a UIView that contains a set of UIImageView subclass objects. The user can drag and rotate the image views via touch. I'm having trouble moving the image view after it has been rotated.
To rotate an image view, I apply a transform rotation, which works fine. It looks like this:
CGAffineTransform trans = self.transform;
self.transform = CGAffineTransformRotate(trans, delta);
The problem comes later when the user tries to move the element via touch. In touchesBegan:WithEvent:, I save the start point in a class variable, startLocation:
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
// Retrieve the touch point
CGPoint pt = [[touches anyObject] locationInView:self];
startLocation = pt;
}
In touchesMoved:withEvent:, I had the following code, which works well enough if there is no rotation transform on the image view:
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
CGPoint pt = [[touches anyObject] locationInView:self];
CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
self.center = newCenter;
}
But if there is a rotation transform on the image view, then the image view thrashes about the screen on each touchesMoved event and soon disappears. In the debugger, I observed that the value of pt became monstrous. It occurred to me that I needed to transform that point, which I did, like so:
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
CGPoint pt = [[touches anyObject] locationInView:self];
if (!CGAffineTransformIsIdentity(self.transform)) {
pt = CGPointApplyAffineTransform(pt, self.transform);
}
CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
}
This worked much better. I can drag the image about the screen now. But the very first movement causes the image to jolt once in one direction or another, depending on the angle of rotation in the transform and the dimensions of the image view.
How can I move the image view without having the initial jolt?
Why is it that I do not need to transform startLocation (the point I capture when touches began)?
It seems you need to convert the coordinates from the main not-rotated object to the rotated-view system.
Take a look at the UIView method "convertPoint:toView:":
Update:
In response to the comments:
You have to get the "real" coordinates of the finger touch (in the non-rotated system), then when the finger moves you always have new coordinates in the main non-rotated view: and they are the point that you have to convert in the rotated view parent of the view that you are moving.
But you see it in 160,250 on the screen,
and if now the user want to move it +20 to the right the user moves the finger +20 in the screen coordinates, not in the B view coordinates, so the user would like to see it in 180,250 of the screen, that means you need to convert this point in the B coordinates system...
So it's a bit easier, you just need to get the screen coordinates of the finger when the user moves it and just convert it in rotated-view coordinates (B)...