使用贝塞尔路径作为裁剪蒙版

24
我想知道是否可以将视图裁剪为Bezier路径。我的意思是,我希望只在封闭Bezier路径内部看到该视图。原因是我有一个不规则形状的轮廓,并且希望逐渐用纯色从上到下填充形状。如果我能够使某个视图仅在路径内可见,那么我可以简单地创建所需颜色的UIView,然后任意更改其框架的y坐标,有效地填充形状。如果有更好的实现方法,我将不胜感激。填充形状将与用户手指的y值匹配,因此它不能是连续动画。谢谢。
更新(很久以后):
我尝试了你的答案 Rob,结果很棒,除了一件事。我的意图是移动被遮罩的视图而保持遮罩在屏幕上的位置不变。这样我就可以给人们留下遮罩被视图“填满”的印象。问题是,根据您的答案编写的代码中,当我移动视图时,遮罩也会随之移动。我明白这是可以预料的,因为我所做的一切只是将它添加为视图的遮罩,因此如果与其联系的东西移动,它就会移动。我尝试将遮罩作为超级视图的子层添加,以使其保持不变,但结果非常奇怪。以下是我的代码:
self.test = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
self.test.backgroundColor = [UIColor greenColor];

[self.view addSubview:self.test];

UIBezierPath *myClippingPath = [UIBezierPath bezierPath];
[myClippingPath moveToPoint:CGPointMake(100, 100)];
[myClippingPath addCurveToPoint:CGPointMake(200, 200) controlPoint1:CGPointMake(self.screenWidth, 0) controlPoint2:CGPointMake(self.screenWidth, 50)];
[myClippingPath closePath];


CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = myClippingPath.CGPath;

self.test.layer.mask = mask;

CGRect firstFrame = self.test.frame;
firstFrame.origin.x += 100;
[UIView animateWithDuration:3 animations:^{
    self.test.frame = firstFrame;
}];

感谢已经提供的帮助。


尝试遮罩self.test的superview。superlayer的遮罩将影响子层,并且只会随着superlayer移动。 - Alex Zielenski
不建议移动视图。我建议使用用户手指的 Y 坐标计算一个矩形。然后在 View 上调用 setNeedsDisplay。在 ViewdrawRect 中填充计算出的矩形。在整个过程中,只需让上述提到的 CAShapeLayer 掩码存在 :):)(虽然我建议您使用路径裁剪,以获得更好的学习体验 :))。干杯! - devluv
2个回答

60
你可以通过将视图的图层遮罩设置为一个CAShapeLayer来轻松实现这一点。
UIBezierPath *myClippingPath = ...

CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = myClippingPath.CGPath;

myView.layer.mask = mask;
你需要将QuartzCore框架添加到你的目标中,如果你还没有添加过。

在Swift中...

let yourCarefullyDrawnPath = UIBezierPath( .. blah blah
let maskForYourPath = CAShapeLayer()
maskForYourPath.path = carefullyRoundedBox.CGPath
layer.mask = maskForYourPath

需要帮助 @robmayoff - jeremyabannister
请注意,这个功能很方便,它确实可以剪裁所有子视图。非常棒。有趣的是(如果我没有弄错的话),“剪裁子视图”参数在这种情况下并不起作用:也就是说,如果你按照Rob在这里解释的做法,它将像这样剪裁子视图,而不管你是否打开了“剪裁子视图”! - Fattie

3
这是Rob解决方案的一个例子,有一个名为smoothViewUIView子视图中放置了一个UIWebViewsmoothView使用bezierPathWithRoundedRect创建了一个圆角灰色背景(请注意右侧)。这很好。
但是如果smoothView只有普通的剪辑子视图,您会得到以下结果: enter image description here 如果按照Rob所说的做,您将获得smoothView所有子视图的圆角效果... enter image description here 真是太棒了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接