Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move a UIImageView after applying CGAffineTransformRotate to it?

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)?

like image 753
richardsun Avatar asked Nov 15 '22 03:11

richardsun


1 Answers

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)_event {
    CGPoint pt = [[touches anyObject] locationInView:self]; 
    startLocation = pt;
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)_event {
    CGPoint pt = [[touches anyObject] previousLocationInView: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;
}

- (void)setRotation:(float)rotation {
    self.transform = CGAffineTransformRotate(self.transform, degreesToRadians(rotation));
}
like image 148
Sergey Vinogradov Avatar answered Dec 28 '22 08:12

Sergey Vinogradov