CGContext剪辑比它应该更多

时间:2014-07-17 17:16:55

标签: ios cgcontext

我有一个UIView,它有3个自定义子视图,其类被调用(现在)LVStemp并且代表树中的节点。 LVStemp的帧大于节点本身,因为它还包括一些位于节点外部的绘图(尚未编码)。 LVStemp有一个名为nodeFrame的属性,它在主视图的坐标中表示节点本身的框架。

我正在尝试绘制节点并用渐变填充它们。但是渐变是以一种不是我想要的方式剪裁。结果如下:

enter image description here

顶部节点填充正确但底部两个不正确。

UIView的超级视图中设置:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 350, 350)];
    [self.view addSubview:myView];

    LVStemp *node1 = [[LVStemp alloc] init];
    node1.frame = CGRectMake(75, 0, 50, 50);
    node1.nodeFrame = node1.frame;
    node1.backgroundColor = [UIColor clearColor];
    [myView addSubview:node1];

    LVStemp *node2 = [[LVStemp alloc] init];
    node2.frame = CGRectMake(0, 25, 100, 175);
    node2.nodeFrame = CGRectMake(0, 150, 50, 50);
    node2.backgroundColor = [UIColor clearColor];
    [myView addSubview:node2];

    LVStemp *node3 = [[LVStemp alloc] init];
    node3.frame = CGRectMake(100, 25, 100, 175);
    node3.nodeFrame = CGRectMake(150, 150, 50, 50);
    node3.backgroundColor = [UIColor clearColor];
    [myView addSubview:node3];
}

LVStemp.h中的代码:

@interface LVStemp : UIView

@property (nonatomic) CGRect nodeFrame; 

@end

LVStemp.m中的代码:

@implementation LVStemp

- (void)drawRect:(CGRect)rect
{
    // Build nodeBounds (= nodeFrame converted to self's coordinate system)
    CGRect nodeBounds = [self convertRect:self.nodeFrame fromView:self.superview];

    // Get CGContextRef
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Draw node with gradient
    [self drawEllipseInRect:nodeBounds withGradient:context];
}

- (void)drawEllipseInRect:(CGRect)rect withGradient:(CGContextRef)context
{
    UIGraphicsPushContext(context);
    CGFloat colors[] = {
        0.1, 0.8, 1.0, 1.0,
        0.1, 0.4, 0.9, 1.0
    };

    CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
    CGColorSpaceRelease(baseSpace), baseSpace = NULL;

    CGContextSaveGState(context);
    CGContextAddEllipseInRect(context, rect);
    CGContextClip(context);

    CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
    CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxX(rect));

    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
    CGGradientRelease(gradient), gradient = NULL;

    CGContextRestoreGState(context);

    CGContextAddEllipseInRect(context, rect);
    CGContextDrawPath(context, kCGPathStroke);
    UIGraphicsPopContext();
}

@end

drawEllipseInRect:withGradient:改编自here。)

如果我注释掉剪辑部分会发生什么:

    //CGContextAddEllipseInRect(context, rect);
    //CGContextClip(context);

enter image description here

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

上下文被剪裁正确,但您正在错误的位置绘制渐变:

CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxX(rect));

更改为使用maxY:

CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

但正如你可能已经注意到的那样,笔画被剪裁了。那是因为它们是以给定轮廓为中心绘制的。你可以考虑用一些插图来调用它:

[self drawEllipseInRect:CGRectInset(nodeBounds, lineWidth/2, lineWidth/2) withGradient:context];