2016-08-02 2 views
9

Уважаемая переполнения стека сообщества,Invert CALayer маска, которая основана на инсульт (без заполнения)

У меня есть проблема, связанная с маской свойство CAShapeLayer в прошивкой (Swift).

То, что я пытаюсь достичь, - это ластик, который стирает части слоя изображения, маскируя его. Проблема возникает, когда я пытаюсь ее инвертировать.

Я нашел несколько хороших ответов на инвертирование пути, но они были полезны только при использовании заполненного пути. То, что я пытаюсь сделать, - это штрих путь и использовать перевернутый, чтобы замаскировать изображение. Ширина линии на штрихе должна составлять примерно 30.0, поэтому она выглядит как ластик.

Я пробовал разные вещи. Моя текущая версия выглядит следующим образом:

  1. Создать CAShapeLayer, который держит путь ластик-тактный
  2. Установите переключатель fill-color слоя к nil
  3. Установите stroke-color и line width
  4. Добавьте слой как маска слоя изображения

Это прекрасно работает, но только делает части изображения видимыми , которые находятся в пределах хода. Я хочу это сделать отменено. Я думал о черно-белой маске, но это не работает, потому что маска передается через альфа-канал.

Есть ли у кого-нибудь идеи, как решить проблему?

+0

Вы также можете добавить любые фотографии, которые описывают то, что вы хотите достичь? –

+0

Я просто могу говорить сам за себя, но у меня есть путь, который является строкой. И wan, чтобы отжать круг (показано на скриншоте). Я хочу скопировать конец строки. (Я не хочу ретушировать сам путь) скриншот: https://d17oy1vhnax1f7.cloudfront.net/items/0b3A3D2H3B3v01221G1I/Screen%20Shot%202016-09-09%20at%2018.43.19.png?v= 1db0e296 –

+0

Умею помогать, но я был бы признателен, если бы вы могли прояснить - ищете ли вы способ создания ластика любым возможным способом или важно, чтобы вы реализовали ластик так, как вы наметили? – Sparky

ответ

3

Вы можете достичь этого, рисуя прозрачными цветами на непрозрачный слой. Это можно сделать, используя другой режим смешивания для рисования. К сожалению, 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 

Я использовал этот код, чтобы нарисовать полупрозрачный круг с прозрачной границей в фронт зеленого фона:

enter image description here

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) { 
     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(self.path!) 
     inContext.drawPath(using: .fillStroke) 
    } 
} 

Примечание: Помечая свойства с @NSManaged вы можете легко сделать свойства анимируемым путем реализации needsDisplay(forKey inKey:) в Swift или needsDisplayForKey: в Objective C, соответственно. Я соответствующим образом адаптировал код Swift.

Но даже если вам не нужны анимации, лучше пометить свойства с помощью @NSManaged, так как QuartzCore создает копии слоев и также должен копировать все свойства с ним. @NSManaged в Swift является аналогом @dynamic в Objective C, поскольку он избегает создания реализации свойства. Вместо этого CALayer получает и задает значения свойств с value(forKey:) и setValue(_:forKey:), соответственно.

Смежные вопросы