开发者

CGContextSetLineWidth of varying width around path

开发者 https://www.devze.com 2023-01-23 02:30 出处:网络
In one of my apps, I have a custom drawn semitransparent UIView that I use as a cover on top of another UIView for a special effect.

In one of my apps, I have a custom drawn semitransparent UIView that I use as a cover on top of another UIView for a special effect.

Lower View:

CGContextSetLineWidth of varying width around path

Lower View with Custom View on Top:

CGContextSetLineWidth of varying width around path

It works, its great on the iPhone where the side margins are only 10 pixels, but now I need to expand the left and right margins to match the row below it.

Here is my code:

- (void)draw:(TTStyleContext*)context {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);

    [_color setStroke];
    CGContextSetLineW开发者_JAVA技巧idth(ctx, MIN(_xwidth, _ywidth));

    CGFloat fw = context.frame.size.width;
    CGFloat fh = context.frame.size.height;

    CGContextMoveToPoint(ctx, fw, floor(fh/2));
    CGContextAddArcToPoint(ctx, fw, fh, floor(fw/2), fh, RD(_radius));
    CGContextAddArcToPoint(ctx, 0, fh, 0, floor(fh/2), RD(_radius));
    CGContextAddArcToPoint(ctx, 0, 0, floor(fw/2), 0, RD(_radius));
    CGContextAddArcToPoint(ctx, fw, 0, fw, floor(fh/2), RD(_radius));
    CGContextClosePath(ctx);
    CGContextStrokePath(ctx);

    CGContextRestoreGState(ctx);

    context.frame = CGRectInset(context.frame, _xwidth/2, _ywidth/2);
    return [self.next draw:context];
}

After setting the _xwidth and _ywidth, the key part of this code is the MIN for the stroke width. The idea here is that the frame is by default, the same stroke width all around. What I am asking it to do is make the stroke width bigger on the sides than on the top and bottom. Using MIN ensures that the stroke does not get the thicker _xwidth size and bleed into the center. If I use the _ywidth value, the sides look great but I don't get the transparent red anymore because the top and bottom borders bleed into the center. This brings me to my question:

Is there a way for me to specify that I want the stroke to be _xwidth thick on the sides and _ywidth thick on the top and bottom? If not, is there another easier way I am overlooking?

With my code, _xwidth set to 42, _ywidth set to 10, I get this:

CGContextSetLineWidth of varying width around path

You can see what I am going for here, and how I need to get the side stroke to cover up the uncovered red background.


I was able to hack it by altering the path and stroking it with the thiner line, then applying another stroke around an expanded rect with the thicker line to mask the overflow

- (void)draw:(TTStyleContext*)context {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);

    CGRect oldFrame = context.frame;

    context.frame = CGRectInset(context.frame, (_xwidth > _ywidth ? _xwidth/2 : 0), (_ywidth > _xwidth ? _ywidth/2 : 0));
    CGFloat ox = (_xwidth > _ywidth ? _xwidth/2 - _ywidth/2 : 0);
    CGFloat oy = (_ywidth > _xwidth ? _ywidth/2 - _xwidth/2 : 0);
    CGFloat fw = context.frame.size.width + ox + (_xwidth > _ywidth ? _ywidth : 0);
    CGFloat fh = context.frame.size.height + oy + (_ywidth > _xwidth ? _xwidth : 0);

    CGContextMoveToPoint(ctx, fw, floor(fh/2));
    CGContextAddArcToPoint(ctx, fw, fh, floor(fw/2), fh, RD(_radius));
    CGContextAddArcToPoint(ctx, ox, fh, ox, floor(fh/2), RD(_radius));
    CGContextAddArcToPoint(ctx, ox, oy, floor(fw/2), oy, RD(_radius));
    CGContextAddArcToPoint(ctx, fw, oy, fw, floor(fh/2), RD(_radius));
    CGContextClosePath(ctx);

    [_color setStroke];
    CGContextSetLineWidth(ctx, MIN(_xwidth, _ywidth));
    CGContextStrokePath(ctx);

    if (_xwidth != _ywidth) {
        CGContextSetLineWidth(ctx, MAX(_xwidth, _ywidth));
        CGContextStrokeRect(ctx, CGRectInset(oldFrame, (_ywidth > _xwidth ? -2*_xwidth : 0), (_xwidth > _ywidth ? -2*_ywidth : 0)));
    }

    CGContextRestoreGState(ctx);

    context.frame = CGRectInset(oldFrame, _xwidth/2, _ywidth/2);
    return [self.next draw:context];
}

CGContextSetLineWidth of varying width around path


It would be a lot simpler to simply fill the same path you're stroking.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号