как нарисовать CALayer с линейным путем, например, имитировать эффект ластика?

Я хочу имитировать эффект ластика с событием касания, чтобы показать изображение, которое за чем-то блокируется сверху, например, серого цвета;

Что-то подобное:

введите здесь описание изображения

Я давно нахожу решение, но не могу сделать это хорошо.

Ниже приведен мой пользовательский код представления: CustomView.m:

-(id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self setup];
    }
    return self;
}

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;

}
-(void)setup
{
    [self setMultipleTouchEnabled:NO];
    [self setBackgroundColor:[UIColor darkGrayColor]];
    self.drawingPath = [UIBezierPath bezierPath];
    [self.drawingPath moveToPoint:CGPointZero];
    [self.drawingPath setLineWidth:5.0];

    self.image = [UIImage imageNamed:@"transformers.jpg"];
    self.shapeLayer = [CAShapeLayer layer];
    self.caLayer = [CALayer layer];
    self.caLayer.frame = self.bounds;
    self.caLayer.contents = (id)(self.image.CGImage);
    [self.layer addSublayer:self.caLayer];
}
- (void)drawRect:(CGRect)rect
{
    self.shapeLayer.path = [self.drawingPath CGPath];

    self.caLayer.mask = self.shapeLayer;
    self.shapeLayer.lineWidth = 5.0;

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self];

    [self.drawingPath moveToPoint:location];
    lastPt = location;
    [self setNeedsDisplay];

    NSLog(@"Touch Began");
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self];

    [self.drawingPath addLineToPoint:location];

    [self setNeedsDisplay];

}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesMoved:touches withEvent:event];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesMoved:touches withEvent:event];
}

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


person Steve Lai    schedule 02.06.2014    source источник
comment
Можете ли вы уточнить, что вы имеете в виду, просто имитируя заполнение пути позади изображения?   -  person Chris    schedule 02.06.2014
comment
Вы думаете об этом неправильно. Создайте фоновый слой серого цвета, а затем создайте слой с реальным изображением. Затем примените путь к реальному изображению и используйте его как маску для серого изображения. Таким образом, без маски он отображается серым, когда вы маскируете реальное изображение, оно просвечивает, а остальное — серое.   -  person MDB983    schedule 02.06.2014
comment
Спасибо, доктор медицины, не могли бы вы дать мне образец/код? потому что я думаю, что концепция этого не проста.   -  person Steve Lai    schedule 02.06.2014


Ответы (1)


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

RevealLayer.h

@interface RevealLayer : CALayer
@property (strong, nonatomic) UIBezierPath *drawingPath;
@end

RevealLayer.m

@implementation RevealLayer
- (UIBezierPath *)drawingPath
{
    if ( !_drawingPath )
    {
        _drawingPath = [UIBezierPath new];
        [_drawingPath moveToPoint:CGPointZero];
        [_drawingPath setLineWidth:20.0];
        [_drawingPath setLineCapStyle:kCGLineCapRound];
    }
    return( _drawingPath );
}

- (void)drawInContext:(CGContextRef)context
{
    UIGraphicsPushContext( context );

    [[UIColor darkGrayColor] set];
    CGContextFillRect( context, self.bounds );

    CGContextSetBlendMode( context, kCGBlendModeClear );
    [self.drawingPath stroke];

    UIGraphicsPopContext();
}
@end

Затем код для пользовательского класса представления аналогичен тому, что у вас уже есть. Однако установка немного отличается, и вам не нужно реализовывать метод drawRect:.

CustomView.m

@interface CustomView()
@property (strong, nonatomic) RevealLayer *revealLayer;
@end

@implementation CustomView
- (void)setup
{
    self.userInteractionEnabled = YES;
    [self setMultipleTouchEnabled:NO];

    self.image = [UIImage imageNamed:@"transformers.jpg"];

    self.revealLayer = [RevealLayer new];
    self.revealLayer.frame = self.bounds;
    self.revealLayer.backgroundColor = [[UIColor clearColor] CGColor];
    [self.revealLayer setNeedsDisplay];

    [self.layer addSublayer:self.revealLayer];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self];

    [self.revealLayer.drawingPath moveToPoint:location];
    [self.revealLayer setNeedsDisplay];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self];

    [self.revealLayer.drawingPath addLineToPoint:location];
    [self.revealLayer setNeedsDisplay];
}
person user3386109    schedule 02.06.2014
comment
Это работает! большое спасибо. Ваш ответ ясен и краток! - person Steve Lai; 03.06.2014
comment
@user3386109 user3386109 .. Можете ли вы дать какое-либо представление о функции отмены для этого стирания слоя .. Если вы знаете, как можно отменить, то, пожалуйста, скажите мне .. - person Milan patel; 08.12.2014
comment
@user3386109 user3386109 Пожалуйста, загрузите свой код, чтобы создать функцию отмены ... Я новичок в iOS ... пожалуйста - person Milan patel; 09.12.2014
comment
@user3386109 user3386109 Пожалуйста, помогите мне в этом stackoverflow.com/questions/27438068/ Я пытаюсь это сделать за последние три дня.. пожалуйста - person Milan patel; 12.12.2014