For someone who wants to adjust direction of animation
I have created an extension for UILabel
to animate font size change
extension UILabel {
func animate(fontSize: CGFloat, duration: TimeInterval) {
let startTransform = transform
let oldFrame = frame
var newFrame = oldFrame
let scaleRatio = fontSize / font.pointSize
newFrame.size.width *= scaleRatio
newFrame.size.height *= scaleRatio
newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * 0.5
newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * 0.5
frame = newFrame
font = font.withSize(fontSize)
transform = CGAffineTransform.init(scaleX: 1 / scaleRatio, y: 1 / scaleRatio);
layoutIfNeeded()
UIView.animate(withDuration: duration, animations: {
self.transform = startTransform
newFrame = self.frame
}) { (Bool) in
self.frame = newFrame
}
}
If you want to adjust direction of animation, use below method and put a suitable anchor point.
SWIFT
struct LabelAnimateAnchorPoint {
// You can add more suitable archon point for your needs
static let leadingCenterY = CGPoint.init(x: 0, y: 0.5)
static let trailingCenterY = CGPoint.init(x: 1, y: 0.5)
static let centerXCenterY = CGPoint.init(x: 0.5, y: 0.5)
static let leadingTop = CGPoint.init(x: 0, y: 0)
}
extension UILabel {
func animate(fontSize: CGFloat, duration: TimeInterval, animateAnchorPoint: CGPoint) {
let startTransform = transform
let oldFrame = frame
var newFrame = oldFrame
let archorPoint = layer.anchorPoint
let scaleRatio = fontSize / font.pointSize
layer.anchorPoint = animateAnchorPoint
newFrame.size.width *= scaleRatio
newFrame.size.height *= scaleRatio
newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * animateAnchorPoint.x
newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * animateAnchorPoint.y
frame = newFrame
font = font.withSize(fontSize)
transform = CGAffineTransform.init(scaleX: 1 / scaleRatio, y: 1 / scaleRatio);
layoutIfNeeded()
UIView.animate(withDuration: duration, animations: {
self.transform = startTransform
newFrame = self.frame
}) { (Bool) in
self.layer.anchorPoint = archorPoint
self.frame = newFrame
}
}
}
OBJECTIVE-C
// You can add more suitable archon point for your needs
#define kLeadingCenterYAnchorPoint CGPointMake(0.f, .5f)
#define kTrailingCenterYAnchorPoint CGPointMake(1.f, .5f)
#define kCenterXCenterYAnchorPoint CGPointMake(.5f, .5f)
#define kLeadingTopAnchorPoint CGPointMake(0.f, 0.f)
@implementation UILabel (FontSizeAnimating)
- (void)animateWithFontSize:(CGFloat)fontSize duration:(NSTimeInterval)duration animateAnchorPoint:(CGPoint)animateAnchorPoint {
CGAffineTransform startTransform = self.transform;
CGRect oldFrame = self.frame;
__block CGRect newFrame = oldFrame;
CGPoint archorPoint = self.layer.anchorPoint;
CGFloat scaleRatio = fontSize / self.font.pointSize;
self.layer.anchorPoint = animateAnchorPoint;
newFrame.size.width *= scaleRatio;
newFrame.size.height *= scaleRatio;
newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * animateAnchorPoint.x;
newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * animateAnchorPoint.y;
self.frame = newFrame;
self.font = [self.font fontWithSize:fontSize];
self.transform = CGAffineTransformScale(self.transform, 1.f / scaleRatio, 1.f / scaleRatio);
[self layoutIfNeeded];
[UIView animateWithDuration:duration animations:^{
self.transform = startTransform;
newFrame = self.frame;
} completion:^(BOOL finished) {
self.layer.anchorPoint = archorPoint;
self.frame = newFrame;
}];
}
@end
For example, to animate changing label font size to 30, duration 1s from center and scale bigger. Simply call
SWIFT
YOUR_LABEL.animate(fontSize: 30, duration: 1, animateAnchorPoint: LabelAnimateAnchorPoint.centerXCenterY)
OBJECTIVE-C
[YOUR_LABEL animateWithFontSize:30
duration:1
animateAnchorPoint:kCenterXCenterYAnchorPoint];