如何使用UIBezierPath填充自定义形状?

时间:2023-02-09 22:01:13

I want to create a custom shape into a UIView by drawing it myself using a UIBezierPath object and render it in drawRect:. So far I managed to create the shape and stroke it so it is drawn on screen exactly how I want it to be. However I can't fill it properly. Here is the code so far:

我想通过使用UIBezierPath对象自己绘制一个自定义形状到UIView中并在drawRect:中呈现出来。到目前为止,我成功地创建了这个形状,并在屏幕上画出了它,这正是我想要的形状。但是我不能把它填满。以下是迄今为止的代码:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(context, 2.f);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path setLineWidth:2.f];
    [path setLineJoinStyle:kCGLineJoinRound];

    // Stroke top left arc
    //[path moveToPoint:CGPointMake(20.f, 2.f)];
    [path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];

    // Stroke bottom left arc
    [path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];

    // Stroke bottom line
    [path moveToPoint:CGPointMake(10.f, 55.f)];
    [path addLineToPoint:CGPointMake(60.f, 55.f)];

    // Stroke bottom arc
    [path moveToPoint:CGPointMake(80.f, 55.f)];
    [path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(315) endAngle:degreesToRadians(215) clockwise:1];

    // Stroke bottom right arc
    [path moveToPoint:CGPointMake(80.f, 55.f)];
    [path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];

    // Stroke top right arc
    [path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];

    // Close path
    [path moveToPoint:CGPointMake(80.f, 5.f)];
    [path addLineToPoint:CGPointMake(10.f, 5.f)];

    [path stroke];
    [path fill];
}

Stroke works as expected, but the fill only fills portions on the path, instead of filling the entire path. Is there something I'm missing?

描边按预期工作,但是填充只填充路径上的部分,而不是填充整个路径。我是不是漏掉了什么?

Thanks in advance!

提前谢谢!

3 个解决方案

#1


3  

Remove all your

删除你所有的

- (void)moveToPoint:(CGPoint)point

methods except the first one because it is a continuous path you don't need it.

方法,除了第一个因为它是一个连续路径你不需要它。

It is highly recommended to close the path by calling the method - (void)closePath because you are having 3 pixel gap.

强烈建议通过调用method - (void)close path关闭路径,因为您有3个像素间隔。

#2


2  

I figured it out. Just needed to get rid of moveToPoint: calls since they create subpaths and so the filling will only affect the new subpaths. And finally called closePath.

我想出来。只需删除moveToPoint:调用,因为它们创建子路径,因此填充只会影响新的子路径。最后叫closePath。

Now my path is continuous and the fill works for the entire shape.

现在我的路径是连续的,整个形状的填充工作。

Edited code:

编辑代码:

- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);

UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:2.f];
[path setLineJoinStyle:kCGLineJoinRound];

// Stroke top left arc
[path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];

// Stroke bottom left arc
[path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];

// Stroke bottom arc
[path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(215) endAngle:degreesToRadians(315) clockwise:0];

// Stroke bottom right arc
[path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];

// Stroke top right arc
[path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];

// Close path
[path closePath];

[path fill];
[path stroke];

}

}

#3


0  

Simply call the method

简单地调用该方法

- (void)closePath

at the end to close your UIBezierPath.

最后关闭UIBezierPath。

#1


3  

Remove all your

删除你所有的

- (void)moveToPoint:(CGPoint)point

methods except the first one because it is a continuous path you don't need it.

方法,除了第一个因为它是一个连续路径你不需要它。

It is highly recommended to close the path by calling the method - (void)closePath because you are having 3 pixel gap.

强烈建议通过调用method - (void)close path关闭路径,因为您有3个像素间隔。

#2


2  

I figured it out. Just needed to get rid of moveToPoint: calls since they create subpaths and so the filling will only affect the new subpaths. And finally called closePath.

我想出来。只需删除moveToPoint:调用,因为它们创建子路径,因此填充只会影响新的子路径。最后叫closePath。

Now my path is continuous and the fill works for the entire shape.

现在我的路径是连续的,整个形状的填充工作。

Edited code:

编辑代码:

- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);

UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:2.f];
[path setLineJoinStyle:kCGLineJoinRound];

// Stroke top left arc
[path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];

// Stroke bottom left arc
[path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];

// Stroke bottom arc
[path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(215) endAngle:degreesToRadians(315) clockwise:0];

// Stroke bottom right arc
[path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];

// Stroke top right arc
[path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];

// Close path
[path closePath];

[path fill];
[path stroke];

}

}

#3


0  

Simply call the method

简单地调用该方法

- (void)closePath

at the end to close your UIBezierPath.

最后关闭UIBezierPath。