You should set your own anchorPoint
Its very much overkill to use a keyframe animation for what really is a change of the anchor point.
The anchor point is the point where all transforms are applied from, the default anchor point is the center. By moving the anchor point to (0,0) you can instead make the layer rotate from the bottom most corner. By setting the anchor point to something where x or y is outside the range 0.0 - 1.0 you can have the layer rotate around a point that lies outside of its bounds.
Please read the section about Layer Geometry and Transforms in the Core Animation Programming Guide for more information. It goes through this in detail with images to help you understand.
EDIT: One thing to remember
The frame of your layer (which is also the frame of your view) is calculated using the position, bounds and anchor point. Changing the anchorPoint will change where your view appears on screen. You can counter this by re-setting the frame after changing the anchor point (this will set the position for you). Otherwise you can set the position to the point you are rotating to yourself. The documentation (linked to above) also mentions this.
Applied to you code
The point you called "transportPoint" should be updated to calculate the difference between the rotation point and the lower left corner of the label divided by the width and height.
// Pseudocode for the correct anchor point
transportPoint = ( (rotationX - labelMinX)/labelWidth,
(rotationX - labelMinY)/labelHeight )
I also made the rotation point an argument to your method. The full updated code is below:
#define DEGREES_TO_RADIANS(angle) (angle/180.0*M_PI)
- (void)rotateText:(UILabel *)label
aroundPoint:(CGPoint)rotationPoint
duration:(NSTimeInterval)duration
degrees:(CGFloat)degrees {
/* Setup the animation */
[UILabel beginAnimations:nil context:NULL];
[UILabel setAnimationDuration:duration];
// The anchor point is expressed in the unit coordinate
// system ((0,0) to (1,1)) of the label. Therefore the
// x and y difference must be divided by the width and
// height of the label (divide x difference by width and
// y difference by height).
CGPoint transportPoint = CGPointMake((rotationPoint.x - CGRectGetMinX(label.frame))/CGRectGetWidth(label.bounds),
(rotationPoint.y - CGRectGetMinY(label.frame))/CGRectGetHeight(label.bounds));
[label.layer setAnchorPoint:transportPoint];
[label.layer setPosition:rotationPoint]; // change the position here to keep the frame
[label.layer setTransform:CATransform3DMakeRotation(DEGREES_TO_RADIANS(degrees), 0, 0, 1)];
/* Commit the changes */
[UILabel commitAnimations];
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…