UIBezierPath draw rectangle and arcs together

家住魔仙堡 提交于 2019-12-11 11:47:17

问题


I want to draw one path like this:

and this is what I wrote :

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];

So I got the result like this

How could I remove the two excrescent lines ? Thanks


回答1:


Just try this:

- (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];
}


You can implement a custom view like so:

@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

then use it:

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



回答2:


Here's what you need, just need to adjust it:

- (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];
}

This is for a landscape Iphone 6+ size, it produces this:

I sized it to full screen so that you are resize it for your needs by using percentages and divisions of entire screen bounds, but this is just an example, that's all. I'll post a few more.

Here's another one, this one closely matches what you have, this is also sized for an iphone 6+, full screen width, you just do the divisions of the numbers by the ratios of (desired height)*(([UIScreen mainScreen].bounds.height)/(736)) and then do the same for the width numbers, but with width obviously, this will resize from iphone 6+ down and up

- (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];
}

and the result:

gray background, iphone 6+ screen, white border, same size dimensions of what you posted:

- (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];
}

Result:

AND, to top this off, here's a category, this is pretty good, you plug in your numbers, and presto you are done:

#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;
}

This last one will work and flex basically however you want it to flex

GIST:

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

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



来源:https://stackoverflow.com/questions/32281721/uibezierpath-draw-rectangle-and-arcs-together

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!