使用 CAShapeLayer 和 UIBezierPath 剪辑屏蔽 uiview
clip-masking uiview with CAShapeLayer and UIBezierPath
我在使用 CAShapeLayer-UIBezierPath 裁剪视图时遇到问题,我想裁剪内容,但我最终得到了那个 UIBezierPath 的笔划(框架),这是我的代码
UIBezierPath *path2Path = [UIBezierPath bezierPath];
[path2Path moveToPoint:CGPointMake(206.745, 0)];
[path2Path addLineToPoint:CGPointMake(206.745, 97.613)];
[path2Path addLineToPoint:CGPointMake(0, 97.613)];
[path2Path addLineToPoint:CGPointMake(0, 0)];
[path2Path addLineToPoint:CGPointMake(87.28, 0)];
[path2Path addCurveToPoint:CGPointMake(103.808, 12.118) controlPoint1:CGPointMake(87.28, 0) controlPoint2:CGPointMake(86.555, 12.118)];
[path2Path addCurveToPoint:CGPointMake(119.466, 0) controlPoint1:CGPointMake(121.061, 12.118) controlPoint2:CGPointMake(119.466, 0)];
[path2Path addLineToPoint:CGPointMake(206.745, 0)];
[path2Path closePath];
[path2Path addClip];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame=MYVIEW.bounds;
pathLayer.path = path2Path.CGPath;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = [[UIColor clearColor] CGColor];
pathLayer.fillRule=kCAFillRuleEvenOdd;
[MYVIEW.layer setMask:pathLayer];
[MYVIEW.layer setMasksToBounds:YES];
MYVIEW.backgroundColor=[UIColor greenColor];
这段代码的结果只是一条绿色的描边线,边界是空的,
像这样
http://i.stack.imgur.com/aehdo.png
但是,我想让边界变成绿色,被那笔画截断
如rob mayoff所述您可以通过将视图的图层蒙版设置为 CAShapeLayer 来轻松完成此操作。
UIBezierPath *myClippingPath = ...
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = myClippingPath.CGPath;
myView.layer.mask = mask;
在Swift
let myClippingPath = UIBezierPath( ... )
let mask = CAShapeLayer()
mask.path = myClippingPath.CGPath
myView.layer.mask = mask
谢谢大家的回答。
如果有人在 SO 上几个小时都找不到合适的答案,就像我刚才做的那样,我已经在 Swift 2.2 中为 masking/clipping UIView 和 CGRect/UIBezierPath:
https://gist.github.com/Flar49/7e977e81f1d2827f5fcd5c6c6a3c3d94
extension UIView {
func mask(withRect rect: CGRect, inverse: Bool = false) {
let path = UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.appendPath(UIBezierPath(rect: self.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.CGPath
self.layer.mask = maskLayer
}
func mask(withPath path: UIBezierPath, inverse: Bool = false) {
let path = path
let maskLayer = CAShapeLayer()
if inverse {
path.appendPath(UIBezierPath(rect: self.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.CGPath
self.layer.mask = maskLayer
}
}
用法:
let viewSize = targetView.bounds.size
let rect = CGRect(x: 20, y: 20, width: viewSize.width - 20*2, height: viewSize.height - 20*2)
// Cuts rectangle inside view, leaving 20pt borders around
targetView.mask(withRect: rect, inverse: true)
// Cuts 20pt borders around the view, keeping part inside rect intact
targetView.mask(withRect: rect)
希望它能在将来节省一些时间:)
您甚至可以使用圆角半径改善@Eugene 的响应(干得好,伙计!)
extension UIView {
func mask(withRect rect: CGRect, cornerRadius: CGFloat = 0, inverse: Bool = false) {
let path = cornerRadius > 0 ?
UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) :
UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.append(UIBezierPath(rect: bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.cgPath
self.layer.mask = maskLayer
}
}
我在使用 CAShapeLayer-UIBezierPath 裁剪视图时遇到问题,我想裁剪内容,但我最终得到了那个 UIBezierPath 的笔划(框架),这是我的代码
UIBezierPath *path2Path = [UIBezierPath bezierPath];
[path2Path moveToPoint:CGPointMake(206.745, 0)];
[path2Path addLineToPoint:CGPointMake(206.745, 97.613)];
[path2Path addLineToPoint:CGPointMake(0, 97.613)];
[path2Path addLineToPoint:CGPointMake(0, 0)];
[path2Path addLineToPoint:CGPointMake(87.28, 0)];
[path2Path addCurveToPoint:CGPointMake(103.808, 12.118) controlPoint1:CGPointMake(87.28, 0) controlPoint2:CGPointMake(86.555, 12.118)];
[path2Path addCurveToPoint:CGPointMake(119.466, 0) controlPoint1:CGPointMake(121.061, 12.118) controlPoint2:CGPointMake(119.466, 0)];
[path2Path addLineToPoint:CGPointMake(206.745, 0)];
[path2Path closePath];
[path2Path addClip];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame=MYVIEW.bounds;
pathLayer.path = path2Path.CGPath;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = [[UIColor clearColor] CGColor];
pathLayer.fillRule=kCAFillRuleEvenOdd;
[MYVIEW.layer setMask:pathLayer];
[MYVIEW.layer setMasksToBounds:YES];
MYVIEW.backgroundColor=[UIColor greenColor];
这段代码的结果只是一条绿色的描边线,边界是空的, 像这样 http://i.stack.imgur.com/aehdo.png
但是,我想让边界变成绿色,被那笔画截断
如rob mayoff所述您可以通过将视图的图层蒙版设置为 CAShapeLayer 来轻松完成此操作。
UIBezierPath *myClippingPath = ...
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = myClippingPath.CGPath;
myView.layer.mask = mask;
在Swift
let myClippingPath = UIBezierPath( ... )
let mask = CAShapeLayer()
mask.path = myClippingPath.CGPath
myView.layer.mask = mask
谢谢大家的回答。
如果有人在 SO 上几个小时都找不到合适的答案,就像我刚才做的那样,我已经在 Swift 2.2 中为 masking/clipping UIView 和 CGRect/UIBezierPath:
https://gist.github.com/Flar49/7e977e81f1d2827f5fcd5c6c6a3c3d94
extension UIView {
func mask(withRect rect: CGRect, inverse: Bool = false) {
let path = UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.appendPath(UIBezierPath(rect: self.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.CGPath
self.layer.mask = maskLayer
}
func mask(withPath path: UIBezierPath, inverse: Bool = false) {
let path = path
let maskLayer = CAShapeLayer()
if inverse {
path.appendPath(UIBezierPath(rect: self.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.CGPath
self.layer.mask = maskLayer
}
}
用法:
let viewSize = targetView.bounds.size
let rect = CGRect(x: 20, y: 20, width: viewSize.width - 20*2, height: viewSize.height - 20*2)
// Cuts rectangle inside view, leaving 20pt borders around
targetView.mask(withRect: rect, inverse: true)
// Cuts 20pt borders around the view, keeping part inside rect intact
targetView.mask(withRect: rect)
希望它能在将来节省一些时间:)
您甚至可以使用圆角半径改善@Eugene 的响应(干得好,伙计!)
extension UIView {
func mask(withRect rect: CGRect, cornerRadius: CGFloat = 0, inverse: Bool = false) {
let path = cornerRadius > 0 ?
UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) :
UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.append(UIBezierPath(rect: bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.cgPath
self.layer.mask = maskLayer
}
}