为什么我的曲线文本本身不对中? [英] Why isn't my curved text centering itself?

查看:115
本文介绍了为什么我的曲线文本本身不对中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 dpCurvedLabel UIView 子类。它使用 CATextLayers 来弧形曲线文本。它工作正常,除了我不能完全集中在图层父视图。我希望圆弧的中心点位于视图的中心(即使视图较小),以便所有文本字符与中心的距离相同。

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

我可以把它关闭,但它总是至少有几个像素关闭。 关闭的数量似乎受到我给每个 CATextLayer 的帧大小的影响。数学有问题,但我不知道是什么。我的代码:




I can get it CLOSE but it's always a at least few pixels off. The amount it's 'off' seems to be effected by the frame size I give each CATextLayer. There's something wrong with the math, but I can't figure out what. My code:

// 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's wrong with the math here? Why won't this text arc center itself?

推荐答案

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

The problem comes from the fact that you are setting the frame of each text layer instead of its position. This means that you are positioning the lower left corner to be at the location 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 your layers to be exactly where you want them.

这篇关于为什么我的曲线文本本身不对中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆