gpt4 book ai didi

ios - 单边角的反向 UIBezierPath

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:16:09 26 4
gpt4 key购买 nike

我想创建一个 mask 路径,其最终输出将是一个带有凹面的角。

我使用 -bezierPathWithRoundedRect:byRoundingCorners:cornerRadii: 方法创建了一个 UIBezierPath 并指定只有一个角需要圆角(在这个例子中, UIRectCornerBottomLeft),我认为通过反转这条路径,我应该首先得到被削减的部分。
为此,我正在尝试 -bezierPathByReversingPath 但它似乎没有任何区别(有或没有因为我得到的是正常的 bezier 路径而不是反向)

这是我目前尝试过的:

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 的红色部分并消除其余区域。

maskPath Idea


目前,我正在做一些像 subview 上的 subview 这样的事情,并将一个 subview 的颜色与主视图的背景颜色同步(糟透了,但至少我得到了所需的输出):

[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 用作一切都是从字面上反转路径,它还在文档中说:

Reversing a path does not necessarily change the appearance of the path when rendered.

编辑:
现在问题中已添加图像,OP 需要形状的倒数:

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;

然后路径的形状是问题中 OP 图像中的红色位。


图片发布前的回答 - 可能用于其他人

下面的代码将产生这个形状:

shape

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 上的类别,因此您可以选择哪些角(UIRectCorner 的位掩码)和半径。

UIBezierPath+RDHConcaveCorners.h

@interface UIBezierPath (RDHConcaveCorners)

+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byConcaveRoundingCorners:(UIRectCorner)corners cornerRadius:(CGFloat)radius;

@end

UIBezierPath+RDHConcaveCorners.m

@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

关于ios - 单边角的反向 UIBezierPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23294308/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com