Why is my curved text not centered?

I have a subclass of UIView called dpCurvedLabel . It uses CATextLayers for curved text around an arc. It works fine, except that I cannot get it completely as a parent representation of the layers. I want the center point for the arc to be in the very center of the view (even if the view is smaller), so all text characters are at the same distance from the center.

I can get it CLOSE, but it always has at least a few pixels. It seems that the amount it turns off is determined by the size of the frame that I give each CATextLayer . Something is wrong with math, but I can’t understand that. My code is:


 // instantiate a dpCurvedLabel in a super view dpCurvedLabel *curvedLabel = [[dpCurvedLabel alloc] initWithFrame:CGRectMake(0, 0, 200, 200) arcSize:360 radius:50 text:@"curve curve curve " font:[UIFont fontWithName:@"HelveticaNeue" size:18] textColor:[UIColor whiteColor]]; // You can animate a rotation to see a more pronounced effect // [curvedLabel rotateContinously]; [self addSubview:curvedLabel]; 

dpCurvedLabel.h

 #import <UIKit/UIKit.h> @interface dpCurvedLabel : UIView @property CGFloat arcSize; @property CGFloat radius; @property (strong) NSString *text; @property (strong) UIFont *font; @property (strong) UIColor *textColor; - (id)initWithFrame:(CGRect)frame arcSize:(CGFloat)arcSize radius:(CGFloat)radius text:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor; - (void)rotateContinously; + (void)makeCurvedText:(CALayer *)layer arcSize:(CGFloat)arcSize radius:(CGFloat)radius text:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor; @end 

dpCurvedLabel.m

 #import "dpCurvedLabel.h" @implementation dpCurvedLabel - (id)initWithFrame:(CGRect)frame arcSize:(CGFloat)arcSize radius:(CGFloat)radius text:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor { self = [super initWithFrame:frame]; if (self) { // Initialization code self.opaque = NO; self.clipsToBounds = NO; self.arcSize = arcSize; self.radius = radius; self.text = text; self.font = font; self.textColor = textColor; } return self; } - (void)layoutSublayersOfLayer:(CALayer *)layer { [super layoutSublayersOfLayer:layer]; NSLog(@"laying out sublayers!"); [dpCurvedLabel makeCurvedText:layer arcSize:self.arcSize radius:self.radius text:self.text font:self.font textColor:self.textColor]; } + (void)makeCurvedText:(CALayer *)layer arcSize:(CGFloat)arcSize radius:(CGFloat)radius text:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor { layer.sublayers = nil; layer.masksToBounds = NO; CGFloat arcStart = 0; CGFloat shiftH = 0; CGFloat shiftV = 0; BOOL clockwise = YES; BOOL debugMode = YES; CGFloat xcenter = CGRectGetMidX(layer.bounds); CGFloat ycenter = CGRectGetMidY(layer.bounds); CGFloat angle = arcStart; CGFloat angleStep = arcSize / text.length; for ( NSUInteger i = 0; i < text.length; ++i ) { NSRange range = { .location = i, .length = 1 }; NSString *c = [text substringWithRange:range]; CGFloat yoffset = sin( degreesToRadians(angle) ) * radius; CGFloat xoffset = cos( degreesToRadians(angle) ) * radius; CGFloat rotAngle = 90 - angle; if ( clockwise ) { yoffset = -yoffset; rotAngle = -90 + angle; } CATextLayer* tl = [[CATextLayer alloc] init]; tl.masksToBounds = NO; tl.wrapped = NO; tl.truncationMode = kCATruncationNone; if ( debugMode ) { tl.borderWidth = 1; tl.cornerRadius = 3; tl.borderColor = [UIColor whiteColor].CGColor; } // Text layer frame determined here. Effects how arc is centered. CGSize charSize = CGSizeMake(20, 20); tl.frame = CGRectMake( shiftH + xcenter - xoffset, shiftV + ycenter + yoffset, charSize.width, charSize.height ); // ******* tl.font = (__bridge CFTypeRef)(font.fontName); tl.fontSize = font.pointSize; tl.foregroundColor = textColor.CGColor; tl.string = c; tl.alignmentMode = @"center"; tl.transform = CATransform3DMakeAffineTransform( CGAffineTransformMakeRotation( degreesToRadians(rotAngle) ) ); [layer addSublayer:tl]; angle += angleStep; } if ( debugMode ) { layer.backgroundColor = RGBA(0x00, 0x00, 0x00, .6).CGColor; } } - (void)rotateContinously { CABasicAnimation *rotationAnimation; rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * 1 * 1 ]; rotationAnimation.duration = 5; rotationAnimation.cumulative = YES; rotationAnimation.repeatCount = INT_MAX; [self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"]; } @end 

What happened to math here? Why won't this text self-center?

0
source share
1 answer

The problem arises because you set the frame of each text layer instead of its position. This means that you are positioning the bottom left corner where the position should be. Do this instead:

  tl.position = CGPointMake( shiftH + xcenter - xoffset, shiftV + ycenter + yoffset); tl.bounds = CGRectMake(0,0,charSize.width,charSize.height); 

And you will find that your layers will be exactly where you want.

+1
source

Source: https://habr.com/ru/post/974515/


All Articles