我想创建一个掩码路径,其最终输出将是带有凹面的角。
我已经使用UIBezierPath
方法创建了一个-bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
,并指定只需要倒圆一个角(在此示例中,UIRectCornerBottomLeft
),我认为通过反转此路径,我应该首先得到应该削减的东西。为此,我正在尝试-bezierPathByReversingPath
,但似乎没有什么区别(有或没有,因为我正在获得正常的贝塞尔曲线路径,而不是相反的路径)]
这是我到目前为止尝试过的:
UIView *vwTest = [[UIView alloc] init];
[vwTest setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[vwTest setBackgroundColor:[UIColor redColor]];
[self.view addSubview:vwTest];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:vwTest.bounds
byRoundingCorners:UIRectCornerBottomLeft
cornerRadii:CGSizeMake(50.0f, 50.0f)];
//get reverse path but doesn't seem to work as I think it should
maskPath = [maskPath bezierPathByReversingPath];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
[maskLayer setFrame:vwTest.bounds];
[maskLayer setPath:maskPath.CGPath];
[vwTest.layer setMask:maskLayer];
[vwTest.layer setMasksToBounds:YES];
[vwTest setNeedsDisplay];
根据下面的图片,我想要实现的是显示UIView
的红色部分,并消除其余区域。
目前,我正在像子视图上一样在子视图上做文章,并将一个子视图的颜色与主视图的背景色同步(糟透了,但至少我得到了所需的输出:]:
[self.view setBackgroundColor:[UIColor lightGrayColor]];
UIView *vwTest = [[UIView alloc] init];
[vwTest setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[vwTest setBackgroundColor:[UIColor redColor]];
[self.view addSubview:vwTest];
UIView *vwPatch = [[UIView alloc] init];
[vwPatch setFrame:vwTest.bounds];
[vwPatch setBackgroundColor:vwTest.superview.backgroundColor];
[vwTest addSubview:vwPatch];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:vwPatch.bounds
byRoundingCorners:UIRectCornerBottomLeft
cornerRadii:CGSizeMake(50.0f, 50.0f)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
[maskLayer setFrame:vwPatch.bounds];
[maskLayer setPath:maskPath.CGPath];
[vwPatch.layer setMask:maskLayer];
[vwPatch.layer setMasksToBounds:YES];
[vwPatch setNeedsDisplay];
有人,请指出正确的方向。
[通过查看问题中的代码,我假设您希望左下角(因为使用UIRectCornerBottomLeft
)是半径为30的凹面。您不能使用bezierPathByReversingPath
,因为它就是全部从字面上反转路径,它也在文档中说:
反转路径不一定会在渲染时改变路径的外观。
编辑:现在已将图像添加到问题中,OP希望形状的倒数:
bezierPathByReversingPath
路径的形状在问题中的OPs图像中为红色。
发布图像之前的答案-可能用于其他人
以下代码将产生这种形状:
CAShapeLayer *mask = [CAShapeLayer layer];
mask.frame = view.layer.bounds;
UIBezierPath *path = [UIBezierPath bezierPath];
CGFloat radius = 50;
CGRect rect = mask.bounds;
[path moveToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect))];
[path addLineToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect) - radius)];
[path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect) - radius) radius:radius startAngle:M_PI endAngle:M_PI_2 clockwise:NO];
[path closePath];
mask.path = path.CGPath;
view.layer.mask = mask;
CGFloat cornerRadius = 30;
CGRect rect = CGRectMake(0, 0, 200, 100);
UIBezierPath *path = [UIBezierPath bezierPath];
// Draw the complete sides
[path moveToPoint:rect.origin];
[path addLineToPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect))];
[path addLineToPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect))];
// Stop short for the start of the arc
[path addLineToPoint:CGPointMake(CGRectGetMinX(rect) + cornerRadius, CGRectGetMaxY(rect))];
// Concave arc
[path addArcWithCenter:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect)) radius:cornerRadius startAngle:0 endAngle:M_PI_2 * 3 clockwise:NO];
// Complete the path
[path closePath];
上的类别,因此您可以选择哪个角(UIBezierPath
s的位掩码)和半径。
UIBezierPath + RDHConcaveCorners.h
UIRectCorner
UIBezierPath + RDHConcaveCorners.m
@interface UIBezierPath (RDHConcaveCorners)
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byConcaveRoundingCorners:(UIRectCorner)corners cornerRadius:(CGFloat)radius;
@end
感谢Rich,支持快捷代码
@implementation UIBezierPath (RDHConcaveCorners)
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byConcaveRoundingCorners:(UIRectCorner)corners cornerRadius:(CGFloat)cornerRadius
{
CGFloat halfWidth = CGRectGetWidth(rect) / 2;
CGFloat halfHeight = CGRectGetHeight(rect) / 2;
if (cornerRadius > halfWidth || cornerRadius > halfHeight) {
cornerRadius = MIN(halfWidth, halfHeight);
}
UIBezierPath *path = [self bezierPath];
CGPoint topLeft = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
if (corners & UIRectCornerTopLeft) {
[path moveToPoint:CGPointMake(topLeft.x, topLeft.y + cornerRadius)];
[path addArcWithCenter:topLeft radius:cornerRadius startAngle:M_PI_2 endAngle:0 clockwise:NO];
} else {
[path moveToPoint:topLeft];
}
CGPoint topRight = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
if (corners & UIRectCornerTopRight) {
[path addLineToPoint:CGPointMake(topRight.x - cornerRadius, topRight.y)];
[path addArcWithCenter:topRight radius:cornerRadius startAngle:M_PI endAngle:M_PI_2 clockwise:NO];
} else {
[path addLineToPoint:topRight];
}
CGPoint bottomRight = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
if (corners & UIRectCornerBottomRight) {
[path addLineToPoint:CGPointMake(bottomRight.x, bottomRight.y - cornerRadius)];
[path addArcWithCenter:bottomRight radius:cornerRadius startAngle:M_PI_2 * 3 endAngle:M_PI clockwise:NO];
} else {
[path addLineToPoint:bottomRight];
}
CGPoint bottomLeft = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
if (corners & UIRectCornerBottomLeft) {
[path addLineToPoint:CGPointMake(bottomLeft.x + cornerRadius, bottomLeft.y)];
[path addArcWithCenter:bottomLeft radius:cornerRadius startAngle:0 endAngle:M_PI_2 * 3 clockwise:NO];
} else {
[path addLineToPoint:bottomLeft];
}
// Complete the path
[path closePath];
return path;
}
@end