0

我有一个UIView名为dpCurvedLabel. 它用于CATextLayers围绕弧线弯曲文本。它工作得很好,除了我不能让它在图层父视图中完全居中。我希望弧的中心点位于视图的中心(即使视图较小),因此所有文本字符与中心的距离相同。

我可以让它关闭,但它总是至少有几个像素。它“关闭”的数量似乎受到我给每个CATextLayer. 数学有问题,但我不知道是什么问题。我的代码:


// 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

这里的数学有什么问题?为什么这个文本不会以自身为中心?

4

1 回答 1

1

问题来自您设置每个文本图层的框架而不是其位置的事实。这意味着您将左下角定位在该位置应该在的位置。改为这样做:

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

你会发现你的图层正好在你想要的地方。

于 2013-04-18T10:07:36.747 回答