Как перерисовать стертое изображение iOS? например, у меня есть одно стертое изображение, я бы хотел, чтобы стертое изображение перерисовывалось при переходе по контексту - PullRequest
1 голос
/ 09 мая 2020

Для стирания Я использую kCGBlendModeClear.

например, у меня есть одно стертое изображение, я бы хотел, чтобы при перемещении по CGContext оно перерисовывалось на стертом изображении.

Изображение: https://www.dropbox.com/s/hsltjqa3ue2dpx8/Simulator%20Screen%20Shot%20-%20iPhone%208%20-%202020-05-09%20at%2019.56.15.png?dl=0

Мой код стирания:


- (void) initialize {

self.userInteractionEnabled = YES;
_tilesFilled = 0;

dragVw = [[UIView alloc] init];
dragVw.backgroundColor = [UIColor redColor];
[dragVw removeFromSuperview];
[self addSubview:dragVw];

if (nil == self.image) {
    _tilesX = _tilesY = 0;
    self.maskedMatrix = nil;
    if (NULL != _imageContext) {
        CGContextRelease(_imageContext);
        _imageContext = NULL;
    }
    if (NULL != _colorSpace) {
        CGColorSpaceRelease(_colorSpace);
        _colorSpace = NULL;
    }
} else {

    self.touchPoints = [NSMutableArray array];
    // CGSize size = self.image.size;
    //        CGSize fromImage = [self aspectScaledImageSizeForImageView:self image:self.image];
    CGSize size = /*CGSizeMake(fromImage.width * pinchScale, fromImage.height * pinchScale);*/ CGSizeMake(self.image.size.width * self.image.scale, self.image.size.height * self.image.scale);

    // initalize bitmap context
    if (NULL == _colorSpace) {
        _colorSpace = CGColorSpaceCreateDeviceRGB();
    }
    if (NULL != _imageContext) {
        CGContextRelease(_imageContext);
    }

    _imageContext = CGBitmapContextCreate(0, size.width, size.height, 8, size.width * 4 , _colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextDrawImage(_imageContext, CGRectMake(0, 0, size.width, size.height), self.image.CGImage);

    int blendMode = kCGBlendModeClear;
    CGContextSetBlendMode(_imageContext, (CGBlendMode) blendMode);

    _tilesX = size.width  / (2 * __radius);
    _tilesY = size.height / (2 * __radius);

    offset = 0;

}

- (void) moveTouches : (NSSet *) касается {

//    CGSize fromImage = [self aspectScaledImageSizeForImageView:self image:self.image];
    CGSize size = /*CGSizeMake(fromImage.width, fromImage.height);*/ CGSizeMake(self.image.size.width * self.image.scale, self.image.size.height * self.image.scale);
    CGContextRef ctx = _imageContext;

    CGContextSetFillColorWithColor(ctx,[UIColor clearColor].CGColor);
    CGContextSetStrokeColorWithColor(ctx,[UIColor colorWithRed:0 green:0 blue:0 alpha:0].CGColor);

// int tempFilled = _tilesFilled;

    // process touches
    for (UITouch *touch in touches) {

        CGContextBeginPath(ctx);
        CGPoint touchPoint = CGPointMake([touch locationInView:self].x , [touch locationInView:self].y);
        touchPoint = fromUItoQuartz(touchPoint, self.bounds.size);
        touchPoint = scalePoint(touchPoint, self.bounds.size, size);

        CGPoint dragPoint = [touch locationInView:self];
        CGFloat fineRadius =  __radius;

        NSLog(@"__radius : %zu",__radius);
        dispatch_async(dispatch_get_main_queue(), ^{
            self->dragVw.frame = CGRectMake(dragPoint.x - fineRadius/2 , dragPoint.y - fineRadius/2, fineRadius, fineRadius);
            self->dragVw.layer.cornerRadius = self->dragVw.frame.size.height / 2;
            self->dragVw.alpha = 0;
//            NSLog(@"DragVw frame : %@",NSStringFromCGRect(self->dragVw.frame));
        });

        if(UITouchPhaseBegan == touch.phase){

            [self.touchPoints removeAllObjects];
            [self.touchPoints addObject:[NSValue valueWithCGPoint:touchPoint]];
            [self.touchPoints addObject:[NSValue valueWithCGPoint:touchPoint]];

            // on begin, we just draw ellipse
            CGRect rect = CGRectMake(touchPoint.x - __radius, touchPoint.y - __radius, __radius*2, __radius*2);
            CGContextAddEllipseInRect(ctx, rect);
            CGContextFillPath(ctx);
            static const FillTileWithPointFunc fillTileFunc = (FillTileWithPointFunc) [self methodForSelector:@selector(fillTileWithPoint:)];
            (*fillTileFunc)(self,@selector(fillTileWithPoint:),rect.origin);

        } else if (UITouchPhaseMoved == touch.phase) {

            [self.touchPoints addObject:[NSValue valueWithCGPoint:touchPoint]];
            // then touch moved, we draw superior-width line
            CGContextSetStrokeColor(ctx, CGColorGetComponents([UIColor clearColor].CGColor));
            CGContextSetLineCap(ctx, kCGLineCapRound);
            CGContextSetLineWidth(ctx, 2 * __radius);


            while(self.touchPoints.count > 3){

                CGPoint bezier[4];
                bezier[0] = ((NSValue*)self.touchPoints[1]).CGPointValue;
                bezier[3] = ((NSValue*)self.touchPoints[2]).CGPointValue;

                CGFloat k = 0.3;
                CGFloat len = sqrt(pow(bezier[3].x - bezier[0].x, 2) + pow(bezier[3].y - bezier[0].y, 2));
                bezier[1] = ((NSValue*)self.touchPoints[0]).CGPointValue;
                bezier[1] = [self normalizeVector:CGPointMake(bezier[0].x - bezier[1].x - (bezier[0].x - bezier[3].x), bezier[0].y - bezier[1].y - (bezier[0].y - bezier[3].y) )];
                bezier[1].x *= len * k;
                bezier[1].y *= len * k;
                bezier[1].x += bezier[0].x;
                bezier[1].y += bezier[0].y;

                bezier[2] = ((NSValue*)self.touchPoints[3]).CGPointValue;
                bezier[2] = [self normalizeVector:CGPointMake( (bezier[3].x - bezier[2].x)  - (bezier[3].x - bezier[0].x), (bezier[3].y - bezier[2].y)  - (bezier[3].y - bezier[0].y) )];
                bezier[2].x *= len * k;
                bezier[2].y *= len * k;
                bezier[2].x += bezier[3].x;
                bezier[2].y += bezier[3].y;


                CGContextMoveToPoint(ctx, bezier[0].x , bezier[0].y + offset );
                CGContextAddCurveToPoint(ctx, bezier[1].x , bezier[1].y + offset, bezier[2].x , bezier[2].y + offset, bezier[3].x , bezier[3].y + offset);


                [self.touchPoints removeObjectAtIndex:0];
            }

            CGContextStrokePath(ctx);

            CGPoint prevPoint = [touch previousLocationInView:self];
            prevPoint = fromUItoQuartz(prevPoint, self.bounds.size);
            prevPoint = scalePoint(prevPoint, self.bounds.size, size);

            static const FillTileWithTwoPointsFunc fillTileFunc = (FillTileWithTwoPointsFunc) [self methodForSelector:@selector(fillTileWithTwoPoints:end:)];
            (*fillTileFunc)(self,@selector(fillTileWithTwoPoints:end:),touchPoint, prevPoint);
        }
    }

}


...