如何使用UIBezierPath裁剪UIView?贝塞尔路径蒙版实现疑问
解决UIBezierPath蒙版裁剪菱形的问题
我一眼就看出你这里的核心问题是坐标系搞混了!你用viewToClip.center来作为贝塞尔路径的起点,但这个坐标是相对于父视图(比如你的根视图)的全局坐标,而CALayer的蒙版路径是基于视图自身图层的本地坐标系——也就是原点在视图左上角,x向右、y向下的坐标系。
举个例子:如果你的viewToClip是100x100的视图,放在屏幕中央,它的center可能是(190, 300)(假设屏幕是375x667),但在它自己的图层坐标系里,中心坐标应该是(50,50),也就是viewToClip.bounds.midX和viewToClip.bounds.midY。
正确的实现代码
你可以这样写,用视图自身的bounds来构建菱形路径:
override func viewDidLoad() { super.viewDidLoad() viewToClip.backgroundColor = .white let viewBounds = viewToClip.bounds let bezierPath = UIBezierPath() // 从视图顶部中点开始 bezierPath.move(to: CGPoint(x: viewBounds.midX, y: viewBounds.minY)) // 画到右侧中点 bezierPath.addLine(to: CGPoint(x: viewBounds.maxX, y: viewBounds.midY)) // 画到底部中点 bezierPath.addLine(to: CGPoint(x: viewBounds.midX, y: viewBounds.maxY)) // 画到左侧中点 bezierPath.addLine(to: CGPoint(x: viewBounds.minX, y: viewBounds.midY)) // 闭合路径 bezierPath.close() // 创建形状图层作为蒙版 let maskLayer = CAShapeLayer() maskLayer.path = bezierPath.cgPath // 给视图图层设置蒙版 viewToClip.layer.mask = maskLayer }
关键细节解释
- 用
viewBounds(视图自身的边界)来获取坐标,所有点都是相对于视图左上角的本地坐标,这样路径会刚好适配视图的大小。 - 最后一定要调用
close()方法闭合路径,不然蒙版可能不会按预期显示——因为贝塞尔路径需要形成封闭的区域才能正确裁剪。 - 如果你的视图大小会变化(比如横竖屏切换),最好把这段代码放到
viewDidLayoutSubviews()里,这样视图 bounds 更新时,蒙版路径也会跟着更新。
这样修改后,你就能得到一个完美的菱形裁剪效果啦!
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

