简体   繁体   中英

UIBezierPath with added arc segment producing phantom triangle

I'm writing a method for creating a UIImageView that contains a transparent UIImage with a rounded bit in either the upper left or upper right corners (if I add this image to a UIView using the same color as the color behind the view, it creates the illusion of a rounded corner - I know about CALayer's rounded corners and I'm not using for a reason).

The code below works as expected if the corner type is UIRectCornerTopLeft . The UIRectCornerTopRight case draws the rounded-over bit in the upper right corner of the image, but for some reason it's also adding a "phantom" filled triangle whose vertices run from the upper left to the lower left to the lower right and back to the upper left. I have no idea where this phantom triangle is coming from, as I don't specify that lower left point anywhere.

Please help, I'm going insane. Here is the code:

+ (UIImageView *)roundedCornerImageOfWidth:(CGFloat)width withCornerBackgroundColor:(UIColor *)cornerColor forCorner:(UIRectCorner)corner {

    CGRect rect = CGRectMake(0, 0, width, width);
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, width), NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // fill image with transparent background
    CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
    CGContextFillRect(context, rect);

    // set the color for solid corner
    CGContextSetFillColorWithColor(context, [cornerColor CGColor]);

    UIBezierPath *maskPath = [UIBezierPath bezierPath];


    switch (corner) {
        case UIRectCornerTopLeft:
        {
            CGPoint pt;
            pt = CGPointMake(0, width); // lower left
            [maskPath moveToPoint:pt];
            pt = CGPointMake(0, 0); // upper left
            [maskPath addLineToPoint:pt];
            pt = CGPointMake(width, 0); // upper right
            [maskPath addLineToPoint:pt];
            // arc back to lower left
            [maskPath addArcWithCenter:CGPointMake(width, width) radius:width startAngle:0 endAngle:-2 * M_PI clockwise:NO];
        }
            break;

        case UIRectCornerTopRight:
        {
            CGPoint pt;
            pt = CGPointMake(0, 0); // upper left
            [maskPath moveToPoint:pt];
            // arc down to lower right
            [maskPath addArcWithCenter:CGPointMake(0, width) radius:width startAngle:0 endAngle:2 * M_PI clockwise:YES];
            pt = CGPointMake(width, 0); // upper right
            [maskPath addLineToPoint:pt];
            pt = CGPointMake(0, 0); // upper left
            [maskPath addLineToPoint:pt];
        }
            break;

        default:
            break;
    }

    [maskPath closePath];
    [maskPath fill];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    imageView.backgroundColor = [UIColor clearColor];
    imageView.frame = CGRectMake(0, 0, width, width);

    return imageView;
}

use 3/2 PI for the start angle and 2 PI for end angle

You can refer to the UIBezierPath docs on how to specify angles. on the first solution 3/2 PI actually refers to the angle made by the line that goes straight up, so the arc starts at the top, 2 PI (which is equivalent to 0, but not here as we need to specify directions ie clockwise/counter-clockwise) is the angle created by the line that goes to the right (in degrees this is 360 degrees (which I'll again point out is on the same place as 0 degrees), so your arc ends at the point intersected by that angle.

Here's the corrected version, in case anybody wants it. Just plain late-night dumbness on my part.

+ (UIImageView *)roundedCornerImageOfWidth:(CGFloat)width 
    withCornerBackgroundColor:(UIColor *)cornerColor 
    forCorner:(UIRectCorner)corner {

    CGRect rect = CGRectMake(0, 0, width, width);
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, width), NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // fill image with transparent background
    CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
    CGContextFillRect(context, rect);

    // set the color for solid corner
    CGContextSetFillColorWithColor(context, [cornerColor CGColor]);

    UIBezierPath *maskPath = [UIBezierPath bezierPath];


    switch (corner) {
        case UIRectCornerTopLeft:
        {
            CGPoint pt;
            pt = CGPointMake(0, width); // lower left
            [maskPath moveToPoint:pt];
            pt = CGPointMake(0, 0); // upper left
            [maskPath addLineToPoint:pt];
            pt = CGPointMake(width, 0); // upper right
            [maskPath addLineToPoint:pt];
            // arc back to lower left
            [maskPath addArcWithCenter:CGPointMake(width, width) 
                radius:width startAngle:0 endAngle:0.5 * M_PI clockwise:NO];
        }
            break;

        case UIRectCornerTopRight:
        {
            // start at upper right
            CGPoint pt;
            pt = CGPointMake(width, 0);
            [maskPath moveToPoint:pt];
            // move to lower right
            pt = CGPointMake(width, width);
            [maskPath addLineToPoint:pt];
            // arc back to upper left
            [maskPath addArcWithCenter:CGPointMake(0, width) radius:width 
                startAngle:2 * M_PI endAngle:1.5 * M_PI clockwise:NO];
            // back to upper right
            pt = CGPointMake(width, 0);
            [maskPath addLineToPoint:pt];
        }
            break;

        default:
            break;
    }

    [maskPath closePath];
    [maskPath fill];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    imageView.backgroundColor = [UIColor clearColor];
    imageView.frame = CGRectMake(0, 0, width, width);

    return imageView;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM