1

我正在尝试使用 Core Graphics 在我的应用程序中绘制一些形状,但在理解将多个形状合并为一个的最佳实践时遇到了一些问题。

这是我想要最终得到的形状(包括颜色)。

圈子 http://www.myquaapps.com/help/lvl1Circle1.png

到目前为止,我已经用正确的笔划画了一个相同大小的圆圈,如下所示:-

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextClearRect(ctx, rect);
    CGContextSetRGBFillColor(ctx, 0, 0, 0, 1);
    CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
    CGContextSetStrokeColor(ctx, red);
    CGContextSetLineWidth(ctx, 18);
    CGContextStrokeEllipseInRect(ctx, CGRectMake(9, 9, 232, 232));
    CGContextFillPath(ctx);

这里的任何帮助将不胜感激!这是我第一次使用 Core Graphics,它看起来正是我所需要的!

4

2 回答 2

4

花了我一点时间,但你走了(所有贝塞尔路径都是实例变量):

编辑:使圆圈的内部透明,但要振作起来,这会很快变得丑陋!

#define LARGE_RADIUS 200
#define SMALL_RADIUS 160

#define RADIANS(degrees) ((degrees) / (180.0 / M_PI))

@implementation MyView
{
    UIBezierPath *largeCircle;
    UIBezierPath *orangeWedge;
    UIBezierPath *yellowWedge;
    UIBezierPath *greenWedge;
    UIBezierPath *whiteCircle;

    UIImage *image;
    void *_imageData;
}

-(void) createPaths {
    largeCircle = [UIBezierPath bezierPathWithArcCenter:self.center radius:LARGE_RADIUS startAngle:0 endAngle:RADIANS(360) clockwise:YES];
    whiteCircle = [UIBezierPath bezierPathWithArcCenter:self.center radius:SMALL_RADIUS startAngle:0 endAngle:RADIANS(360) clockwise:YES];    

    orangeWedge = [UIBezierPath bezierPath];
    [orangeWedge moveToPoint:self.center];

    double startAngle = RADIANS(45);
    double endAngle = RADIANS(135);

    [orangeWedge addLineToPoint:CGPointMake(sin(startAngle) + self.center.x, cos(startAngle) + self.center.y)];
    [orangeWedge addArcWithCenter:self.center radius:LARGE_RADIUS startAngle:startAngle endAngle:endAngle clockwise:YES];
    [orangeWedge addLineToPoint:self.center];

    startAngle = RADIANS(60);
    endAngle = RADIANS(120);

    yellowWedge = [UIBezierPath bezierPath];
    [yellowWedge moveToPoint:self.center];

    [yellowWedge addLineToPoint:CGPointMake(sin(startAngle) + self.center.x, cos(startAngle) + self.center.y)];
    [yellowWedge addArcWithCenter:self.center radius:LARGE_RADIUS startAngle:startAngle endAngle:endAngle clockwise:YES];
    [yellowWedge addLineToPoint:self.center];

    startAngle = RADIANS(75);
    endAngle = RADIANS(105);

    greenWedge = [UIBezierPath bezierPath];
    [greenWedge moveToPoint:self.center];

    [greenWedge addLineToPoint:CGPointMake(sin(startAngle) + self.center.x, cos(startAngle) + self.center.y)];
    [greenWedge addArcWithCenter:self.center radius:LARGE_RADIUS startAngle:startAngle endAngle:endAngle clockwise:YES];
    [greenWedge addLineToPoint:self.center];
}

-(void) drawPaths
{
    [[UIColor blackColor] setStroke];
    [[UIColor redColor] setFill];
    [largeCircle fill];
    [largeCircle stroke];
    [[UIColor orangeColor] setFill];
    [orangeWedge fill];
    [orangeWedge stroke];
    [[UIColor yellowColor] setFill];
    [yellowWedge fill];
    [yellowWedge stroke];
    [[UIColor greenColor] setFill];
    [greenWedge fill];
    [greenWedge stroke];

    [whiteCircle stroke];
}

-(int32_t *) pixelAt:(int) x :(int) y
{
    return &((int32_t *)_imageData)[x + (y * (int) self.frame.size.width)];
}

-(void) removeInnerCircle
{
    int32_t invisible = 0;

    int centerX = self.center.x;
    int centerY = self.center.y;

    for (int i = SMALL_RADIUS - 1; i > 0; i--) {
        float incr = (22.0 / i);

        for (float j = 0; j <= 360; j += incr) {
            float angle = RADIANS(j);

            *[self pixelAt:(sin(angle) * i + centerX) :(cos(angle) * i + centerY)] = invisible;
        }
    }
}

-(void) setUpContext
{
    size_t width  = self.frame.size.width;
    size_t height = self.frame.size.height;

    _imageData = malloc(4 * width * height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef context = CGBitmapContextCreate(_imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    CGContextTranslateCTM(context, 0, height);
    CGContextScaleCTM(context, 1, -1);

    assert(context != NULL);

    UIGraphicsPushContext(context);

    CGContextRelease(context);
}

-(void) destroyContext
{
    CGImageRef imageRef = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());

    assert(imageRef != NULL);

    image = [UIImage imageWithCGImage:imageRef];

    UIGraphicsPopContext();

    free(_imageData);
    _imageData = NULL;
}

-(void) awakeFromNib
{    
    [self createPaths];

    [self setUpContext];

    [self drawPaths];
    [self removeInnerCircle];

    [self destroyContext];    
}

-(void) drawRect:(CGRect)rect
{
    [image drawInRect:self.frame];
}

@end

根据 的值SMALL_RADIUS,您可能希望更改jin的增量-removeInnerCircle,以便它不会执行不必​​要的循环。

更改代码以j根据当前半径进行增量,因此您越接近中心,需要更改的像素就越少!

于 2012-05-09T17:51:50.903 回答
2

我会通过创建圆形路径、设置粗线宽度,然后使用CGContextReplacePathWithStrokedPath(). 这将形成一条实际上是两个同心圆的新路径。

CGContextBeginPath(ctx);
CGRect rect = CGRectMake(9, 9, 232, 232);
CGContextAddEllipseInRect(ctx, CGRectInset(rect, 16, 16));
CGContextSetLineWidth(ctx, 32);
CGContextReplacePathWithStrokedPath(ctx);

现在您可以为圆环的黑色边缘设置线条粗细和颜色并对其进行描边。这得到内部和外部黑色同心圆:

CGContextSetLineWidth(ctx, 32);
CGContextSetGrayStrokeColor(ctx, 0, 1);
CGContextStrokePath(ctx);

设置填充颜色并填充:

CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
CGContextFillPath(ctx);

现在剪辑到它:

CGContextClip(ctx);

现在您可以绘制橙色、黄色和绿色的形状,它们将被剪裁到环内。我不清楚 Richard 的代码是否完全正确地处理了这些形状。他使用以圆环中心为中心的楔形,但在您的图片中,边缘似乎并不都指向中心。(此外,他画了一个白色圆圈来“擦除”内部部分,而您的图片在内部是透明的。)设置剪裁后,您可以只绘制三角形或任何最方便的方式来使这些边缘按您的方式倾斜想要它们,它们会自动被限制在环上。

于 2012-05-09T18:26:32.320 回答