Search code examples
iosobjective-ccgaffinetransform

Rotating a view using another view's center as the anchor point


I have two image views. The first is the blueish arrow, and the second is the white circle, with a black dot drawn to represent the center of the circle.

I'm trying to rotate the arrow so it's anchor point is the black dot in the picture like this

enter image description here

Right now I'm setting the anchor point of the arrow's layer to a point calculated like this

CGFloat y = _userImageViewContainer.center.y - CGRectGetMinY(_directionArrowView.frame);
CGFloat x = _userImageViewContainer.center.x - CGRectGetMinX(_directionArrowView.frame);
CGFloat yOff = y / CGRectGetHeight(_directionArrowView.frame);
CGFloat xOff = x / CGRectGetWidth(_directionArrowView.frame);

_directionArrowView.center = _userImageViewContainer.center;

CGPoint anchor = CGPointMake(xOff, yOff);
NSLog(@"anchor: %@", NSStringFromCGPoint(anchor));

_directionArrowView.layer.anchorPoint = anchor;

Since the anchor point is set as a percentage of the view, i.e. the coords for the center are (.5, .5), I'm calculating the percentage of the height in arrow's frame where the black dot falls. But my math, even after working out by hand, keeps resulting in .5, which isn't right because it's further than half way down when the arrow is in the original position (vertical, with the point up).

I'm rotating based on the user's compass heading

CLHeading *heading = [notif object];

// update direction of arrow
CGFloat degrees = [self p_calculateAngleBetween:[PULAccount currentUser].location.coordinate
                                            and:_user.location.coordinate];


_directionArrowView.transform = CGAffineTransformMakeRotation((degrees - heading.trueHeading) * M_PI / 180);

The rotation is correct, it's just the anchor point that's not working right. Any ideas of how to accomplish this?


Solution

  • I've always found the anchor point stuff flaky, especially with rotation. I'd try something like this.

        CGPoint convertedCenter = [_directionArrowView convertPoint:_userImageViewContainer.center fromView:_userImageViewContainer ];
    
         CGSize offset = CGSizeMake(_directionArrowView.center.x - convertedCenter.x, _directionArrowView.center.y - convertedCenter.y);
     // I may have that backwards, try the one below if it offsets the rotation in the wrong direction..
    //  CGSize offset = CGSizeMake(convertedCenter.x -_directionArrowView.center.x , convertedCenter.y - _directionArrowView.center.y); 
         CGFloat rotation = 0; //get your angle (radians)
    
         CGAffineTransform tr = CGAffineTransformMakeTranslation(-offset.width, -offset.height);
              tr = CGAffineTransformConcat(tr, CGAffineTransformMakeRotation(rotation) );
              tr = CGAffineTransformConcat(tr, CGAffineTransformMakeTranslation(offset.width, offset.height) );
    
    
        [_directionArrowView setTransform:tr];
    

    NB. the transform property on UIView is animatable, so you could put that last line there in an animation block if desired..