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

Posted

技术标签:

【中文标题】使用贝塞尔路径作为剪贴蒙版【英文标题】:Use Bezier Path as Clipping Mask 【发布时间】:2013-12-22 23:49:12 【问题描述】:

我想知道是否可以将视图剪辑到贝塞尔路径。我的意思是我希望只能在封闭的贝塞尔路径内的区域中看到视图。这样做的原因是我有一个不规则形状的轮廓,我想从上到下用纯色逐渐填充形状。如果我可以使某个视图仅在路径中可见,那么我可以简单地创建一个我想要的颜色的 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 的超级视图。超层的遮罩会影响子层,并且只会随着超层移动。 而不是移动视图。我建议您使用来自用户手指的Y 坐标计算矩形。然后在View 上拨打setNeedsDisplay。在视图的drawRect 内填充计算出的矩形。在整个过程中,只需让上面提到的CAShapeLayer 掩码在那里 :) :) (尽管我建议您使用路径剪辑,以获得更好的学习体验 :))。干杯 【参考方案1】:

您可以通过将视图的图层蒙版设置为CAShapeLayer 轻松做到这一点。

UIBezierPath *myClippingPath = ...

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

myView.layer.mask = mask;

如果您还没有将QuartzCore 框架添加到您的目标,则需要。


在斯威夫特...

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

【讨论】:

需要帮助@robmayoff 请注意,这确实会剪切所有子视图。非常棒。有趣的是(如果我没记错的话)“clip subviews”参数不能“工作”这个:即,如果你按照 Rob 的解释,它像这样剪辑子视图,无论您是否打开或关闭“剪辑子视图”!【参考方案2】:

只是 Rob 解决方案的一个示例,有一个 UIWebView 作为 UIView子视图,称为 smoothViewsmoothView 使用 bezierPathWithRoundedRect 制作圆形灰色背景(注意在右侧)。效果很好。

但如果smoothView 只有正常的剪辑子视图,你会得到这个:

如果你按照 Rob 说的去做,你会得到 smoothView 中的圆角 和所有子视图 ...

好东西。

【讨论】:

以上是关于使用贝塞尔路径作为剪贴蒙版的主要内容,如果未能解决你的问题,请参考以下文章

从简单的图像 ios 创建贝塞尔路径

如何使用 CSS 在两个图像之间创建剪辑路径 [关闭]

阴影不适用于带有蒙版的 UIViewLayer

在 3d 中沿贝塞尔路径移动对象:旋转问题

贝塞尔曲线与CAShapeLayer的关系以及Stroke动画

iOS 使用贝塞尔曲线绘制路径