Implementing touch-based rotation in cocoa touch

Posted by ewoo on Stack Overflow See other posts from Stack Overflow or by ewoo
Published on 2010-05-06T11:04:13Z Indexed on 2010/05/06 11:08 UTC
Read the original article Hit count: 675

I am wondering what is the best way to implement rotation-based dragging movements in my iPhone application.

I have a UIView that I wish to rotate around its centre, when the users finger is touch the view and they move it. Think of it like a dial that needs to be adjusted with the finger.

The basic question comes down to:

1) Should I remember the initial angle and transform when touchesBegan is called, and then every time touchesMoved is called apply a new transform to the view based on the current position of the finger, e.g., something like:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

  UITouch *touch = [touches anyObject];
  CGPoint currentPoint = [touch locationInView:self]; //current position of touch   

 if (([touch view] == self) 
    &&  [Utility getDistance:currentPoint toPoint:self.middle] <= ROTATE_RADIUS //middle is centre of view
    && [Utility getDistance:currentPoint toPoint:self.middle] >= MOVE_RADIUS) { //will be rotation gesture

  //remember state of view at beginning of touch
  CGPoint top = CGPointMake(self.middle.x, 0);
  self.initialTouch = currentPoint;
  self.initialAngle = angleBetweenLines(self.middle, top, self.middle, currentPoint);   
  self.initialTransform = self.transform;
 }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

  UITouch *touch = [touches anyObject];
  CGPoint currentPoint = [touch locationInView:self]; //current position of touch

  if (([touch view] == self) 
  &&  [Utility getDistance:currentPoint toPoint:self.middle] <= ROTATE_RADIUS
  && [Utility getDistance:currentPoint toPoint:self.middle] >= MOVE_RADIUS) { //a rotation gesture

  //rotate tile
  float newAngle = angleBetweenLines(self.middle, CGPointMake(self.middle.x, 0), self.middle, currentPoint); //touch angle
  float angleDif = newAngle - self.initialAngle; //work out dif between angle at beginning of touch and now.
  CGAffineTransform newTransform = CGAffineTransformRotate(self.initialTransform, angleDif); //create new transform
  self.transform = newTransform;  //apply transform.
}

OR

2) Should I simply remember the last known position/angle, and rotate the view based on the difference in angle between that and now, e.g.,:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

      UITouch *touch = [touches anyObject];
      CGPoint currentPoint = [touch locationInView:self]; //current position of touch   

     if (([touch view] == self) 
        &&  [Utility getDistance:currentPoint toPoint:self.middle] <= ROTATE_RADIUS
        && [Utility getDistance:currentPoint toPoint:self.middle] >= MOVE_RADIUS) { //will be rotation gesture

      //remember state of view at beginning of touch
      CGPoint top = CGPointMake(self.middle.x, 0);
      self.lastTouch = currentPoint;
      self.lastAngle = angleBetweenLines(self.middle, top, self.middle, currentPoint);  
     }
    }

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

      UITouch *touch = [touches anyObject];
      CGPoint currentPoint = [touch locationInView:self]; //current position of touch

      if (([touch view] == self) 
      &&  [Utility getDistance:currentPoint toPoint:middle] <= ROTATE_RADIUS
      && [Utility getDistance:currentPoint toPoint:middle] >= MOVE_RADIUS) { //a rotation gesture

      //rotate tile
      float newAngle = angleBetweenLines(self.middle, CGPointMake(self.middle.x, 0), self.middle, currentPoint); //touch angle
      float angleDif = newAngle - self.lastAngle; //work out dif between angle at beginning of touch and now.
      CGAffineTransform newTransform = CGAffineTransformRotate(self.transform, angleDif); //create new transform

      self.transform = newTransform;  //apply transform.
      self.lastTouch = currentPoint;
      self.lastAngle = newAngle;
    }

The second option makes more sense to me, but it is not giving very pleasing results (jaggy updates and non-smooth rotations). Which way is best (if any), in terms of performance?

Cheers!

© Stack Overflow or respective owner

Related posts about iphone

Related posts about cocoa-touch