Нарисуйте прямоугольник, используя Core Graphics с предварительным просмотром - PullRequest
1 голос
/ 04 мая 2010

Я создаю простое приложение для рисования и хотел бы помочь с рисованием прямоугольников на основе событий касания пользователя. Я могу нарисовать прямоугольник, используя Core Graphics, от точки в штрихах Began до точки в штрихах закругленной. Этот прямоугольник затем отображается после запуска события touchesEnded.

Тем не менее, я бы хотел сделать это «вживую». Это означает, что прямоугольник обновляется и отображается, когда пользователь перетаскивает палец. Это возможно? Любая помощь будет принята с благодарностью, спасибо!

UPDATE:

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

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        _firstPoint = [touch locationInView:self.view];
        _firstPoint.y -= 40;
        _lastPoint = _firstPoint;
    }

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        CGPoint currentPoint = [touch locationInView:self.view];
        currentPoint.y -= 40;

        [self drawSquareFrom:_firstPoint to:currentPoint];

        _lastPoint = currentPoint;
    }

    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        CGPoint currentPoint = [touch locationInView:self.view];
        currentPoint.y -= 40;

        [self drawSquareFrom:_firstPoint to:currentPoint];

        [_modifiedImage release];
        _modifiedImage = [[UIImage alloc] initWithCGImage:_imageView.image.CGImage];
    }

    - (void)drawSquareFrom:(CGPoint)firstPoint to:(CGPoint)lastPoint
    {
        _imageView.image = _modifiedImage;

        CGFloat width  = lastPoint.x - firstPoint.x;
        CGFloat height = lastPoint.y - firstPoint.y;

        _path = [UIBezierPath bezierPathWithRect:CGRectMake(firstPoint.x, firstPoint.y, width, height)];

        UIGraphicsBeginImageContext( _originalImage.size );
        [_imageView.image drawInRect:CGRectMake(0, 0, _originalImage.size.width, _originalImage.size.height)];

        _path.lineWidth = 10;
        [[UIColor redColor] setStroke];
        [[UIColor clearColor] setFill];
        [_path fill];
        [_path stroke];

        _imageView.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }

Ответы [ 2 ]

0 голосов
/ 01 июня 2012

Просто используйте два контекста. В одном из них вы просто «просматриваете» рисование прямоугольника и можете очистить его на TouchesMoved. На TouchesEnd вы, наконец, опираетесь на исходный контекст, а затем на изображение.

0 голосов
/ 06 мая 2010

То, что вы делаете сейчас, - это создание парных CGImage и CGBitmapContext для каждого вызова на drawSquareFrom:to: и их удаление каждый раз. Вместо этого создайте отдельные парные CGImage и CGBitmapContext, которые вы будете использовать для каждого вызова.

-(void) drawSquareFrom:(CGPoint)from to:(CGPoint)to {
    CGContextRef context = [self offscreenContext];
    CGRect draw , full = [self offscreenContextBounds];

    draw.origin = from;
    draw.size.width = to.x - from.x;
    draw.size.height = to.y - from.y;
    draw = CGRectStandardize( draw );

    [[UIColor redColor] setStroke];
    [[UIColor clearColor] setFill];
    CGContextClearRect( context , full );
    CGContextFillRect( context , draw );
    CGContextStrokeRectWithWidth( context , draw , 10 );
    [_imageView setNeedsDisplay];
}

Вы создаете парные CGImage и CGContext, как это, хотя есть некоторые ... для заполнения. Все переменные myX предназначены для членов класса.

-(CGContextRef) offscreenContext {
    if ( nil == myContext ) {
        size_t width = 400;
        size_t height = 300;
        CFMutableDataRef data = CFDataCreateMutable( NULL , width * height * 4 ); // 4 is bytes per pixel
        CGDataProviderRef provider = CGDataProviderCreateWithCFData( data );
        CGImageRef image = CGImageCreate( width , height , ... , provider , ... );
        CGBitmapContextRef context = CGBitmapContextCreate( CFDataGetMutableBytePtr( data ) , width , height , ... );
        CFRelease( data ); // retained by provider I think
        CGDataProviderRelease( provider ); // retained by image

        myImage = image;
        myContext = context;
        myContextFrame.origin = CGPointZero;
        myContextFrame.size.width = width;
        myContextFrame.size.height = height;
        _imageView.image = [UIImage imageWithCGImage:image];
    }

    return myContext;
}
-(CGRect) offscreenContextBounds {
    return myContextFrame;
}

Устанавливает _imageView.image для вновь созданного изображения. В drawSquareFrom:to: я предполагаю, что setNeedsDisplay достаточно, чтобы нарисовать сделанные изменения, но может случиться так, что вам нужно будет каждый раз назначать новый UIImage, который оборачивает тот же CGImage.

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