当使用相同坐标绘制的图像形成圆弧时,CGRect 中绘制的文本标签形成椭圆弧

text labels drawn in CGRect form an elliptical arc when images drawn using the same coordinates form a circular arc

我是 Core Graphics 的新手,我想了解为什么我在 CGRect 中绘制的文本标签形成椭圆弧,而我使用相同坐标绘制的图像形成圆弧。

Arthur Knopper 的原始代码会在触摸屏幕的任何地方创建圆圈。通过删除 touches 方法,我已经能够沿着圆弧(超级圆)生成一系列小圆(点)。每个点都以超级圆的周长为中心(如下所示)。

为了标记每个点,我使用与放置点相同的点坐标。然而,文本标签形成椭圆弧,即使点形成圆弧(如下所示)。当点被填充时,标签也会被点隐藏。其原因完全是个谜。

作为新手,我可能缺少 Core Graphics 中的一些基本知识。如果有人能解释那是什么以及我需要做什么才能使两个圆弧都变成圆形并将标签放在点的顶部,我将不胜感激。

谢谢。

这是代码。

    circleView.h

    NSMutableArray  *totalCircles;

    int            dotCount, limit;

    float         uberX, uberY, uberRadius, uberAngle, labelX,
                    labelY,dotRadius, dotsFilled, sectors, x, y;

    CGPoint         dotPosition;
    CGRect          boxBoundary;
    CGContextRef    context;
}

- (void)demo;

@end

还有...

-@implementation iOSCircleView

- (id)initWithFrame:(CGRect)frame   {
    self = [super initWithFrame:frame];
    if (self) {

        // Initialization code
        totalCircles            = [[NSMutableArray alloc] init];

        // Set background color
        self.backgroundColor    = [UIColor whiteColor];
    }
    return self;
}   // frame a view for drawing



- (void)drawRect:(CGRect)rect       {
     [self demo];
}


- (void)demo                        {
        context          = UIGraphicsGetCurrentContext();
        CGContextSetLineWidth(context, 0.5);

        uberX           =   120;
        uberY           =   160;
        uberRadius      =   30;
        sectors         =   16;
        uberAngle       =   (2.0 * PI) / sectors;

        dotRadius       =   20;
        dotsFilled      =   FALSE;

        for (dotCount   = 1; dotCount <= sectors; dotCount++)
        {
            // Create a new iOSCircle Object
            iOSCircle *newCircle    = [[iOSCircle alloc] init];
            newCircle.circleRadius  = dotRadius;
            [self setSectorDotCoordinates];        // make new point for each dot
            dotPosition             = CGPointMake(x,y);         // create each dot

            NSLog(@"Circle%i: %@", dotCount, NSStringFromCGPoint(dotPosition));

            [self autoLabel];                      // text hides behind the dots

            newCircle.circleCentre  = dotPosition; // place each dot on the frame
            [totalCircles addObject:newCircle];
            [self setNeedsDisplay];
        }

        CGContextSetShadowWithColor(context, CGSizeMake(-3 , 2), 4.0, [UIColor clearColor].CGColor);
        dotCount = 1;
        for (iOSCircle *circle in totalCircles) {
            CGContextAddArc(context, circle.circleCentre.x, circle.circleCentre.y, circle.circleRadius, 0.0, M_PI * 2.0, YES);               // draw the circles

            NSLog(@"Dot %i Filled %i ", dotCount, dotsFilled);
            switch (dotsFilled) {
                case 1:
                    CGContextSetFillColorWithColor(context, [[UIColor cyanColor] CGColor]);
                    //CGContextDrawPath(context, kCGPathFillStroke);
                    break;
                    default:
                    //CGContextStrokePath(context);    // draw dot outline
                    break;
            }
            dotCount++;
        }
    }   //  draw circular dots in circular patterns

- (void)setSectorDotCoordinates     {

    x           = uberX + (uberRadius * cos(uberAngle *dotCount) * 2);
    y           = uberY + (uberRadius * sin(uberAngle *dotCount) * 2);    
}   // calculate dot coordinates along a circular arc

- (void)autoLabel {
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
    boxBoundary = CGRectMake(x-dotRadius, y-dotRadius, x+dotRadius, y+dotRadius);
    [[NSString stringWithFormat:@"%i",dotCount] drawInRect:boxBoundary withFont:[UIFont systemFontOfSize:24] lineBreakMode:NSLineBreakByCharWrapping alignment:NSTextAlignmentCenter];
}

更改autoLabel中的boxBoundaryCGRectMake创建一个点坐标和宽度和高度的矩形,而不是两个点:

(void)autoLabel { 
 CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
 boxBoundary = CGRectMake(x-dotRadius, y-dotRadius, dotRadius*2, dotRadius*2); 
 [[NSString stringWithFormat:@"%i",dotCount] drawInRect:boxBoundary 
                                             withFont:[UIFont systemFontOfSize:24] 
                                        lineBreakMode:NSLineBreakByCharWrapping alignment:NSTextAlignmentCenter]; 
}

在您的代码中,"boxes" 包含的文本在您向右移动时会越来越大。 (宽度和高度不固定)

我更新后的代码显示的标签与绘图顺序相匹配,但填充点后文本仍然隐藏。

我怀疑我需要构建一个路径来在点前面写入文本,并且已经很明显需要像 CGPathMoveToPoint 这样的东西来从 12 点钟的位置开始绘制。

这是更新后的代码。第一部分绘制和渲染点

    context          = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 0.5);

    uberX           =   160;
    uberY           =   240;
    uberRadius      =   52;
    sectors         =   16;
    uberAngle       =   ((2.0 * PI) / sectors);

    NSLog(@"%f %f %f %f", uberX, uberY, uberRadius, uberAngle);

    dotRadius       =   20;
    dotsFilled      =   FALSE;

    textOffset      =   4;      // add to y to centre the label

    for (dotCount   = 1; dotCount <= 4 /*sectors*/; dotCount++)
    {
        // Create a new iOSCircle Object
        iOSCircle *newCircle    = [[iOSCircle alloc] init];
        newCircle.circleRadius  = dotRadius;
        [self setSectorDotCoordinates];                     // create a new point for each dot
        dotPosition             = CGPointMake(x,y);         // create each dot

        NSLog(@"Circle%i: %@", dotCount, NSStringFromCGPoint(dotPosition));

        newCircle.circleCentre  = dotPosition;              // place each dot on the frame
        [totalCircles addObject:newCircle];
        [self setNeedsDisplay];
    }

    CGContextSetShadowWithColor(context, CGSizeMake(-3 , 2), 4.0, [UIColor clearColor].CGColor);
    dotCount = 1;
    for (iOSCircle *circle in totalCircles) {

        CGContextAddArc(context, circle.circleCentre.x, circle.circleCentre.y, circle.circleRadius, 0.0, M_PI * 2.0, YES);
        // draw the circles

        NSLog(@"Dot %i Filled %i ", dotCount, dotsFilled);
        switch (dotsFilled) {
            case 1:
                CGContextSetFillColorWithColor(context, [[UIColor cyanColor] CGColor]);
                CGContextDrawPath(context, kCGPathFillStroke);
                break;
                default:
                CGContextStrokePath(context);      // draw dot outline
                break;
        }

        [self setSectorDotCoordinates];             // find point coordinates for each dot

        dotCount++;
    }

紧随其后的是绘制标签的代码。

    // draw labels

for (dotCount   = 1; dotCount <= sectors; dotCount++)
{
    // Create a new iOSCircle Object
    iOSCircle *newCircle    = [[iOSCircle alloc] init];
    newCircle.circleRadius  = dotRadius;
    [self setSectorDotCoordinates];                 // find point coordinates for each dot

    dotPosition             = CGPointMake(x,y);     // use point coordinates for label
    [self autoLabel];                               // THIS SHOWS TEXT BEHIND THE DOTS
}