如何获取 UIBezierPath 的反向路径
Posted
技术标签:
【中文标题】如何获取 UIBezierPath 的反向路径【英文标题】:How to Get the reverse path of a UIBezierPath 【发布时间】:2012-06-25 14:33:51 【问题描述】:self.myPath=[UIBezierPath bezierPathWithArcCenter:center
radius:200
startAngle:0
endAngle:180
clockwise:YES];
(通过一些网络搜索,我就可以开始运行了)。
我有这条路。现在我想填充这条路径的反面,所以留下这部分并填充其他所有内容。我怎样才能完成编码?我没有太多这方面的信息。
问题
之前使用 Cemal Answer 后显示的区域只显示了一个带有红色笔划的圆圈。
编辑
- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
self.backgroundColor = [UIColor whiteColor];
self.punchedOutPath =
[UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 400, 400)];
self.fillColor = [UIColor redColor];
self.alpha = 0.8;
return self;
- (void)drawRect:(CGRect)rect
[[self fillColor] set];
UIRectFill(rect);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut);
[[self punchedOutPath] fill];
CGContextSetBlendMode(ctx, kCGBlendModeNormal);
【问题讨论】:
它是一个完整的圆形还是一个开放的圆形?另外,你能提供一张你所期待的图片吗?它不一定要漂亮,但它会极大地帮助人们了解您正在尝试做什么,以便他们可以帮助您。 done..一直在努力提供它,因为我做了赏金 【参考方案1】:使用bezierPathByReversingPath
。来自文档(仅限 ios 6.0+):
使用与当前路径相反的内容创建并返回一个新的贝塞尔路径对象。
所以要扭转你的道路,你只需:
UIBezierPath* aPath = [UIBezierPath bezierPathWithArcCenter:center
radius:200
startAngle:0
endAngle:180
clockwise:YES];
self.myPath = [aPath bezierPathByReversingPath];
【讨论】:
或者只是reversing()
在 swift 中。【参考方案2】:
这是一个完全不需要反转路径的替代方案。
您实际上想要“剪掉”视图的一部分:
假设您希望白色区域为[UIColor whiteColor]
,alpha 为 75%。以下是您快速完成的方法:
UIView
子类。
这个视图有两个属性:
@property (retain) UIColor *fillColor;
@property (retain) UIBezierPath *punchedOutPath;
您覆盖其-drawRect:
方法来执行此操作:
- (void)drawRect:(CGRect)rect
[[self fillColor] set];
UIRectFill(rect);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut);
[[self punchedOutPath] fill];
CGContextSetBlendMode(ctx, kCGBlendModeNormal);
这里有一个警告:视图的fillColor
必须不包含 alpha 组件。所以在你的情况下,你希望它只是[UIColor whiteColor]
。然后,您可以通过调用 [myView setAlpha:0.75]
自己应用 alpha 位。
这里发生了什么:这是使用一种名为“Destination Out”的混合模式。在数学上它被定义为R = D*(1 - Sa)
,但通俗地说,它的意思是“目标图像不透明但源图像透明的目标图像,并且在其他地方透明。”
所以它将使用目的地(即上下文中已经存在的内容),只要 new 东西是透明的(即在贝塞尔路径之外),然后贝塞尔路径将是不透明的,那东西会变得透明。但是,目标内容必须已经是不透明的。如果它不是不透明的,则混合不会达到您想要的效果。这就是为什么你必须提供一个不透明的UIColor
,然后直接对视图进行任何你想要的透明度。
我自己运行了这个,在这些情况下:
窗口有一个[UIColor greenColor]
背景
fillColor
是白色的
punchedOutPath
是一个椭圆形,距离视图边缘 10 个点。
视图有一个alpha
或0.75
通过上面的代码,我明白了:
内部是纯绿色,外面有半透明的覆盖层。
更新
如果您的覆盖物是图像,那么您需要创建一个新图像。但原理是一样的:
UIImage* ImageByPunchingPathOutOfImage(UIImage *image, UIBezierPath *path)
UIGraphicsBeginImageContextWithOptions([image size], YES, [image scale]);
[image drawAtPoint:CGPointZero];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut);
[path fill];
UIImage *final = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return final;
然后您将获取此函数的结果并将其放入UIImageView
。
【讨论】:
你能把你的项目提供给我吗??请..!这会更好,因为我会有一个工作代码..否则我将不得不与你澄清问题..这可能会让你很烦!. @shubhank 答案中的代码描述了您需要的一切 嗨..你能检查我对问题的新编辑吗..我尝试了你的方法..我将视图的背景设置为白色..但是椭圆形是黑色的..你能帮我解决一下吗……应该是白色的……谢谢 @Shubhank 这种方法不适用于backgroundColor
的UIView
。您看到的黑色是视图在打孔视图(可能是窗口)之后的颜色。
我打算将图像添加到视图中并在其上具有上述功能...如果它不能与UIView
一起使用...我将如何裁剪图像.. ?请给个建议..您帮了很多忙,如果您能帮我解决这个问题,那就太好了..非常感谢【参考方案3】:
您可以将其放入视图控制器中的单屏应用程序中:它将创建一个黄色背景视图和一个蓝色层,上面有一个被蒙版切掉的椭圆区域。
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// create a yellow background
UIView *bg = [[UIView alloc] initWithFrame:self.view.bounds];
bg.backgroundColor = [UIColor yellowColor];
[self.view addSubview:bg];
// create the mask that will be applied to the layer on top of the
// yellow background
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.fillRule = kCAFillRuleEvenOdd;
maskLayer.frame = self.view.frame;
// create the paths that define the mask
UIBezierPath *maskLayerPath = [UIBezierPath bezierPath];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:CGRectInset(self.view.bounds, 20, 20)]];
// here you can play around with paths :)
// [maskLayerPath appendPath:[UIBezierPath bezierPathWithOvalInRect:(CGRect)80, 80, 140, 190]];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithOvalInRect:(CGRect)100, 100, 100, 150]];
maskLayer.path = maskLayerPath.CGPath;
// create the layer on top of the yellow background
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = self.view.layer.bounds;
imageLayer.backgroundColor = [[UIColor blueColor] CGColor];
// apply the mask to the layer
imageLayer.mask = maskLayer;
[self.view.layer addSublayer:imageLayer];
这也可以回答这个问题:UIBezierPath Subtract Path
【讨论】:
您能解释一下您在做什么以及为什么吗?让提问的人和寻找答案的其他人明白你的答案是什么。 奇怪,为什么 [UIBezierPath bezierPathWithOvalInRect:] 不画一个椭圆?您是否将该代码准确地复制并粘贴到了一个空的单屏项目中?【参考方案4】:我有两个解决方案给你。
在CALayer
上绘制这条路径。并将 CALayer
用作实际 CALayer
的遮罩层。
在添加圆弧之前用你的框架大小绘制一个矩形。
UIBezierPath *path = [UIBezierPath bezierPathWithRect:view.frame];
[path addArcWithCenter:center
radius:200
startAngle:0
endAngle:2*M_PI
clockwise:YES];
我会使用第二种解决方案。 :)
【讨论】:
第二种方案更好,只是弧线需要逆时针添加,所以它所划定的区域被the nonzero winding number rule排除(矩形是顺时针方向添加的)。 这对我不起作用我得到了一个非常奇怪的结果..我在问题中添加了它..请看..谢谢 endAngle 必须是弧度(不是度数)。你想要一个 360° 的圆,所以是 2pi 或 6.283。你可以写成2*M_PI
。以上是关于如何获取 UIBezierPath 的反向路径的主要内容,如果未能解决你的问题,请参考以下文章