How do I draw lines with alpha < 1 in quartz 2d

2020-02-13 03:42发布

No doubt this might be a duplicate question but I am not able to get proper solution from any post here. So I am posting this as new post with a hope that I get some solution.

I my drawing app I want to give a feature of opacity for lines to be drawn. But when I assign alpha to color, I am getting overlapped points in between the line.

Some where I found that drawing in two views solves this issue, but I was not able to understand the logic behind that.

enter image description here

I am using normal quartz 2d code to draw line on touch events.

4条回答
ら.Afraid
2楼-- · 2020-02-13 03:59

Hie..

This is my final solution.. I am now drawing lines on drawRect event and drawing the entire line at a time as a path.. This creates opacity to retain and now no line caps drawn in between..

No doubt this is the trick that is working since I am drawing on every touch and this works..

- (void)drawRect:(CGRect)rect {
for (int j=0; j<[pathArray count]; j++) 
{
    context = UIGraphicsGetCurrentContext();
    NSMutableDictionary *tmp=[pathArray objectAtIndex:j];
    NSMutableArray *currentPath=[tmp objectForKey:@"path"];
    for (int i=0; i<[currentPath count]; i++) 
    {
        CGPoint mid1 = [[self midPoint:[currentPath objectAtIndex:i+1]  :[currentPath objectAtIndex:i]] CGPointValue]; 
        CGPoint mid2 = [[self midPoint:[currentPath objectAtIndex:i+2] :[currentPath objectAtIndex:i+1]] CGPointValue];
        CGContextMoveToPoint(context, mid1.x, mid1.y);
        CGContextAddQuadCurveToPoint(context, [[currentPath objectAtIndex:i+1] CGPointValue].x, [[currentPath objectAtIndex:i+1] CGPointValue].y, mid2.x, mid2.y); 
        CGContextSetShadow(context, CGSizeMake(-2, -2), 3);
        CGContextSetAlpha(context, [[tmp objectForKey: @"opacity"] floatValue]);    
        CGContextSetLineCap(context, kCGLineCapRound);
        CGContextSetStrokeColorWithColor(context,[[tmp objectForKey: @"Color"] CGColor]);               
        CGContextSetLineWidth(context, [[tmp objectForKey: @"width"] floatValue]);              
        i+=2;
    }   
    CGContextStrokePath(context);

}
}
查看更多
Bombasti
3楼-- · 2020-02-13 04:05

It looks like you're drawing a circle at every point of a series of touch events. Instead, you can build a Path with CoreGraphics/Quartz2D, set the line width to be whatever thickness, and then stroke that path as needed to keep the UI looking nice. I've not done this in a while, but I think most of what you need will be in CoreGraphics/CGContext.h and ~/CGPath.h, etc. See my answer to another CoreGraphics problem here.

The one unknown in my mind right now is whether you can stroke a CGMutablePathRef to a context before you 'close' it using CGPathCloseSubpath(). You'll have to experiment. At any rate, as you receive mouse events, you will build a path up with the new points and render it a little at a time. Let me know if you need clarification.

P.S. as for opacity, you will set it when you create the CGColorRef for your context... many of the calls in CoreGraphics/CGColor.h have an alpha parameter.

查看更多
疯言疯语
4楼-- · 2020-02-13 04:13

Duplicate of In CoreGraphics drawing how can I keep the point of overlap from being darker than the rest of the line?

The trick is to have the brush stroke in its own buffer, where you can clip the alpha properly before blending the whole thing with the background.

Here's one way to do that: Create 2 views, one for the background, another one for the lines. Draw the lines in the top view with an alpha of 1! Then set the alpha of this whole foreground view to 0.5 (or whatever value you want to use).

[topView setAlpha:0.5];

That will prevent a semi-transparent brush stroke from intensifying itself. But what about 2 different brush strokes that cross each other (like in your example). Do you want that intersection to be more intense? If so, then you need to create a new view for every brush stroke. To prevent memory overflow for having too many views, you then need to blend the previous top view(s) with the background.

查看更多
三岁会撩人
5楼-- · 2020-02-13 04:20
#pragma mark -
#pragma mark Touch Event

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

    lastPoint = [touch locationInView:drawView];
}

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];   
    CGPoint currentPoint = [touch locationInView:drawView];

    UIGraphicsBeginImageContext(drawView.frame.size);

    [drawImage.image drawInRect:CGRectMake(0, 0, drawView.frame.size.width, drawView.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1.0);
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
    CGContextBeginPath(UIGraphicsGetCurrentContext());
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    lastPoint = currentPoint;

}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    UIGraphicsBeginImageContext(drawView.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, drawView.frame.size.width, drawView.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1.0);
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    CGContextFlush(UIGraphicsGetCurrentContext());
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}
查看更多
登录 后发表回答