亲爱的堆栈溢出社区,
我在iOS(Swift)中与CAShapeLayer
的mask属性有关。
我要实现的是一个eraser,它通过掩盖来擦除图像层的一部分。当我尝试将其反转时,问题就来了。
我在反转路径时找到了一些很好的答案,但是这些仅在使用filled路径时有用。我尝试做的是stroke路径,并使用倒置的路径来遮盖图像。笔画上的线宽应大约为30.0
,因此它看起来像橡皮擦。
我尝试了不同的事情。我当前的版本如下所示:
CAShapeLayer
来保存橡皮擦行程的路径fill-color
设置为nil
stroke-color
和line width
这很好,但是仅使图像的部分可见[[在笔画内]。我想做reversed。我想到了黑白蒙版,但这不起作用,因为该蒙版是通过Alpha通道传递的。
有人知道如何解决问题吗?CAShapeLayer
不支持此功能。因此,您必须编写自己的形状图层类:@interface ShapeLayer : CALayer
@property(nonatomic) CGPathRef path;
@property(nonatomic) CGColorRef fillColor;
@property(nonatomic) CGColorRef strokeColor;
@property(nonatomic) CGFloat lineWidth;
@end
@implementation ShapeLayer
@dynamic path;
@dynamic fillColor;
@dynamic strokeColor;
@dynamic lineWidth;
- (void)drawInContext:(CGContextRef)inContext {
CGContextSetGrayFillColor(inContext, 0.0, 1.0);
CGContextFillRect(inContext, self.bounds);
CGContextSetBlendMode(inContext, kCGBlendModeSourceIn);
if(self.strokeColor) {
CGContextSetStrokeColorWithColor(inContext, self.strokeColor);
}
if(self.fillColor) {
CGContextSetFillColorWithColor(inContext, self.fillColor);
}
CGContextSetLineWidth(inContext, self.lineWidth);
CGContextAddPath(inContext, self.path);
CGContextDrawPath(inContext, kCGPathFillStroke);
}
@end
创建具有透明路径的层:
ShapeLayer *theLayer = [ShapeLayer layer]; theLayer.path = ...; theLayer.strokeColor = [UIColor clearColor].CGColor; theLayer.fillColor = [UIColor colorWithWhite:0.8 alpha:0.5]; theLayer.lineWith = 3.0; theLayer.opaque = NO; // Important, otherwise you will get a black rectangle
我已经使用此代码在绿色背景前面绘制了一个带有透明边框的半透明圆:Edit:这是Swift中图层的相应代码:
public class ShapeLayer: CALayer { @NSManaged var path : CGPath? @NSManaged var fillColor : CGColor? @NSManaged var strokeColor : CGColor? @NSManaged var lineWidth : CGFloat override class func defaultValue(forKey inKey: String) -> Any? { return inKey == "lineWidth" ? 1.0 : super.defaultValue(forKey: inKey) } override class func needsDisplay(forKey inKey: String) -> Bool { return inKey == "path" || inKey == "fillColor" || inKey == "strokeColor" || inKey == "lineWidth" || super.needsDisplay(forKey: inKey) } override public func draw(in inContext: CGContext) { if let thePath = path { inContext.setFillColor(gray: 0.0, alpha: 1.0) inContext.fill(self.bounds) inContext.setBlendMode(.sourceIn) if let strokeColor = self.strokeColor { inContext.setStrokeColor(strokeColor) } if let fillColor = self.fillColor { inContext.setFillColor(fillColor) } inContext.setLineWidth(self.lineWidth) inContext.addPath(thePath) inContext.drawPath(using: .fillStroke) } } }
注:通过用
但是,即使您不需要动画,也最好用@NSManaged
标记属性,可以分别通过在Swift中实现needsDisplay(forKey inKey:)
或在目标C中实现needsDisplayForKey:
轻松地使属性具有动画性。我已经相应地修改了Swift代码。@NSManaged
标记属性,因为QuartzCore会复制图层,并且还应该复制所有属性。 Swift中的@NSManaged
与目标C中的@dynamic
是对等的,因为它避免了创建属性实现。相反,CALayer
分别使用value(forKey:)
和setValue(_:forKey:)
获取并设置属性值。