UIBezierPath 一起绘制矩形和圆弧

Posted

技术标签:

【中文标题】UIBezierPath 一起绘制矩形和圆弧【英文标题】:UIBezierPath draw rectangle and arcs together 【发布时间】:2015-08-29 01:06:49 【问题描述】:

我想画一条这样的路径:

这就是我写的:

CGFloat radius = 50;

UIBezierPath *path = [UIBezierPath bezierPath];

[path moveToPoint:CGPointMake(radius, CGRectGetMinY(rect))];

[path addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect))];
[path addLineToPoint:CGPointMake(CGRectGetMaxX(rect) -radius, CGRectGetMaxY(rect))];
[path addLineToPoint:CGPointMake(radius, CGRectGetMaxY(rect))];
[path closePath];
UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, CGRectGetMinY(rect) + radius) radius:radius startAngle:0.5 * M_PI endAngle:1.5 *M_PI clockwise:YES];

UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMaxY(rect) - radius) radius:radius startAngle:-0.5 * M_PI endAngle:0.5 *M_PI clockwise:YES];


[path1 appendPath:path];
[path1 appendPath:path2];

所以我得到了这样的结果

我怎样才能去掉两条多余的线?谢谢

【问题讨论】:

为什么不使用UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; 【参考方案1】:

试试这个:

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

    const CGFloat radius = 50;
    const CGFloat lineWidth = 10;

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, lineWidth / 2, lineWidth / 2)
                                                    cornerRadius:radius];

    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    path.lineWidth = lineWidth;
    [path stroke];

    CGContextSetFillColorWithColor(context, [UIColor grayColor].CGColor);
    [path fill];


您可以像这样实现自定义视图:

@interface RoundedView: UIView

@property (nonatomic, strong) UIColor *strokeColor;
@property (nonatomic, strong) UIColor *fillColor;

@end

@implementation RoundedView

- (instancetype)initWithFrame:(CGRect)frame 
    self = [super initWithFrame:frame];
    if (self) 
        self.backgroundColor = [UIColor clearColor];
    
    return self;


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

    const CGFloat radius = 50;
    const CGFloat lineWidth = 10;

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, lineWidth / 2, lineWidth / 2)
                                                    cornerRadius:radius];

    CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor);
    path.lineWidth = lineWidth;
    [path stroke];

    CGContextSetFillColorWithColor(context, self.fillColor.CGColor);
    [path fill];


@end

然后使用它:

RoundedView *view = [[RoundedView alloc] initWithFrame:CGRectMake(10, 20, 200, 100)];
[self.view addSubview:view];

【讨论】:

是的,你是对的。我通过 CGPath 解决了它,但你的答案更简单 很高兴能帮到你:)【参考方案2】:

这是你需要的,只需要调整它:

- (void)drawSkateboard: (CGRect)frame 
    UIColor* fillColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
    UIBezierPath* bezierPath = UIBezierPath.bezierPath;
    [bezierPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 529, CGRectGetMinY(frame) + 414)];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 207, CGRectGetMinY(frame) + 414)];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + 207) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 93.2, CGRectGetMinY(frame) + 414) controlPoint2: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + 320.9)];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + 207)];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 207, CGRectGetMinY(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + 93.2) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 93.1, CGRectGetMinY(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 529, CGRectGetMinY(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 736, CGRectGetMinY(frame) + 207) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 642.8, CGRectGetMinY(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 736, CGRectGetMinY(frame) + 93.1)];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 736, CGRectGetMinY(frame) + 207)];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 529, CGRectGetMinY(frame) + 414) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 736, CGRectGetMinY(frame) + 320.9) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 642.9, CGRectGetMinY(frame) + 414)];
    [bezierPath closePath];
    bezierPath.miterLimit = 4;
    [fillColor setFill];
    [bezierPath fill];

这是针对 Iphone 6+ 尺寸的风景,它会产生这个:

我将其调整为全屏,以便您通过使用整个屏幕边界的百分比和分割来调整其大小,但这只是一个示例,仅此而已。我会再发一些。

这是另一个,这个与你所拥有的非常匹配,这也是为 iphone 6+ 设计的,全屏宽度,你只需按照 (期望高度)*(([UIScreen mainScreen].bounds.height)/(736)) 然后对宽度数字执行相同操作,但显然宽度会从 iphone 6+ 向下和向上调整大小

- (void)drawSkateboard: (CGRect)frame 

    UIColor* color = [UIColor colorWithRed: 0.451 green: 0.416 blue: 1 alpha: 1];
    UIBezierPath* bezierPath = UIBezierPath.bezierPath;
    [bezierPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.87704 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.71739 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.12296 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.71739 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.49879 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.05530 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.71739 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.61908 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.49879 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.12296 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.28019 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37850 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.05530 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.28019 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.87704 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.28019 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 1.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.49879 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.94470 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.28019 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 1.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37850 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 1.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.49879 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.87704 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.71739 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 1.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.61908 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.94470 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.71739 * CGRectGetHeight(frame))];
    [bezierPath closePath];
    bezierPath.miterLimit = 4;

    [color setFill];
    [bezierPath fill];

结果:

灰色背景,iphone 6+ 屏幕,白色边框,与您发布的尺寸相同:

- (void)drawSkateboard: (CGRect)frame  
    UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame), 736, 414)];
    [UIColor.lightGrayColor setFill];
    [rectanglePath fill];

    UIBezierPath* bezierPath = UIBezierPath.bezierPath;
    [bezierPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.82853 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.69300 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.17147 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.69300 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.06291 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50000 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.11182 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.69300 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.06291 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.60628 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.06291 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50000 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.17147 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.30700 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.06291 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.39396 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.11168 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.30700 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.82853 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.30700 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.93709 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50000 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.88818 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.30700 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.93709 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.39372 * CGRectGetHeight(frame))];
    [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.93709 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50000 * CGRectGetHeight(frame))];
    [bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.82853 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.69300 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.93709 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.60604 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.88818 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.69300 * CGRectGetHeight(frame))];
    [bezierPath closePath];
    bezierPath.miterLimit = 4;

    [UIColor.blueColor setFill];
    [bezierPath fill];
    [UIColor.whiteColor setStroke];
    bezierPath.lineWidth = 5.5;
    [bezierPath stroke];

结果:

而且,最重要的是,这是一个类别,这非常好,你插入你的数字,然后你就完成了:

#define TOP_LEFT(X, Y)\
    CGPointMake(rect.origin.x + X * limitedRadius,\
                rect.origin.y + Y * limitedRadius)
#define TOP_RIGHT(X, Y)\
    CGPointMake(rect.origin.x + rect.size.width - X * limitedRadius,\
                rect.origin.y + Y * limitedRadius)
#define BOTTOM_RIGHT(X, Y)\
    CGPointMake(rect.origin.x + rect.size.width - X * limitedRadius,\
                rect.origin.y + rect.size.height - Y * limitedRadius)
#define BOTTOM_LEFT(X, Y)\
    CGPointMake(rect.origin.x + X * limitedRadius,\
                rect.origin.y + rect.size.height - Y * limitedRadius)

+ (UIBezierPath*)bezierPathWithios7RoundedRect: (CGRect)rect cornerRadius: (CGFloat)radius 

    UIBezierPath* path = UIBezierPath.bezierPath;
    CGFloat limit = MIN(rect.size.width, rect.size.height) / 2 / 1.52866483;
    CGFloat limitedRadius = MIN(radius, limit);

    [path moveToPoint: TOP_LEFT(1.52866483, 0.00000000)];
    [path addLineToPoint: TOP_RIGHT(1.52866471, 0.00000000)];
    [path addCurveToPoint: TOP_RIGHT(0.66993427, 0.06549600)
            controlPoint1: TOP_RIGHT(1.08849323, 0.00000000)
            controlPoint2: TOP_RIGHT(0.86840689, 0.00000000)];
    [path addLineToPoint: TOP_RIGHT(0.63149399, 0.07491100)];
    [path addCurveToPoint: TOP_RIGHT(0.07491176, 0.63149399)
            controlPoint1: TOP_RIGHT(0.37282392, 0.16905899)
            controlPoint2: TOP_RIGHT(0.16906013, 0.37282401)];
    [path addCurveToPoint: TOP_RIGHT(0.00000000, 1.52866483)
            controlPoint1: TOP_RIGHT(0.00000000, 0.86840701)
            controlPoint2: TOP_RIGHT(0.00000000, 1.08849299)];
    [path addLineToPoint: BOTTOM_RIGHT(0.00000000, 1.52866471)];
    [path addCurveToPoint: BOTTOM_RIGHT(0.06549569, 0.66993493)
            controlPoint1: BOTTOM_RIGHT(0.00000000, 1.08849323)
            controlPoint2: BOTTOM_RIGHT(0.00000000, 0.86840689)];
    [path addLineToPoint: BOTTOM_RIGHT(0.07491111, 0.63149399)];
    [path addCurveToPoint: BOTTOM_RIGHT(0.63149399, 0.07491111)
            controlPoint1: BOTTOM_RIGHT(0.16905883, 0.37282392)
            controlPoint2: BOTTOM_RIGHT(0.37282392, 0.16905883)];
    [path addCurveToPoint: BOTTOM_RIGHT(1.52866471, 0.00000000)
            controlPoint1: BOTTOM_RIGHT(0.86840689, 0.00000000)
            controlPoint2: BOTTOM_RIGHT(1.08849323, 0.00000000)];
    [path addLineToPoint: BOTTOM_LEFT(1.52866483, 0.00000000)];
    [path addCurveToPoint: BOTTOM_LEFT(0.66993397, 0.06549569)
            controlPoint1: BOTTOM_LEFT(1.08849299, 0.00000000)
            controlPoint2: BOTTOM_LEFT(0.86840701, 0.00000000)];
    [path addLineToPoint: BOTTOM_LEFT(0.63149399, 0.07491111)];
    [path addCurveToPoint: BOTTOM_LEFT(0.07491100, 0.63149399)
            controlPoint1: BOTTOM_LEFT(0.37282401, 0.16905883)
            controlPoint2: BOTTOM_LEFT(0.16906001, 0.37282392)];
    [path addCurveToPoint: BOTTOM_LEFT(0.00000000, 1.52866471)
            controlPoint1: BOTTOM_LEFT(0.00000000, 0.86840689)
            controlPoint2: BOTTOM_LEFT(0.00000000, 1.08849323)];
    [path addLineToPoint: TOP_LEFT(0.00000000, 1.52866483)];
    [path addCurveToPoint: TOP_LEFT(0.06549600, 0.66993397)
            controlPoint1: TOP_LEFT(0.00000000, 1.08849299)
            controlPoint2: TOP_LEFT(0.00000000, 0.86840701)];
    [path addLineToPoint: TOP_LEFT(0.07491100, 0.63149399)];
    [path addCurveToPoint: TOP_LEFT(0.63149399, 0.07491100)
            controlPoint1: TOP_LEFT(0.16906001, 0.37282401)
            controlPoint2: TOP_LEFT(0.37282401, 0.16906001)];
    [path addCurveToPoint: TOP_LEFT(1.52866483, 0.00000000)
            controlPoint1: TOP_LEFT(0.86840701, 0.00000000)
            controlPoint2: TOP_LEFT(1.08849299, 0.00000000)];
    [path closePath];
    return path;

最后一个基本上可以工作和弯曲,但你希望它弯曲

要点:

https://gist.github.com/anonymous/1e86aedc1a7c204cd7fb

https://gist.github.com/anonymous/0b7a7f08bbd1f2622d9a

【讨论】:

以上是关于UIBezierPath 一起绘制矩形和圆弧的主要内容,如果未能解决你的问题,请参考以下文章

使用 UIBezierPath 绘制 100 多个不同位置的圆圈

为啥cornerRadius的最大值不是矩形的一半?用 UIBezierPath 快速绘制roundedRect

拖动并缩放使用 UIBezierPath IOS/Swift 绘制的矩形

UIview 的快照不显示圆弧和圆角

Canvas中怎么绘制圆和圆弧

iOS开发之Quartz2D 二:绘制直线,曲线,圆弧,矩形,椭圆,圆