3

我一直在玩一个自定义视图,它看起来像 Quartz 作曲家的补丁对象。我的假 Quartz Composer 视图看起来不错。这是一个单一的视图,具有 2 个不同的线性渐变、一个阴影和顶部的一条高光线,

假 Quartz Composer 用户界面。

我想将其扩展为圆角。这对于渐变等非常简单,但是,我不确定如何沿着视图顶部绘制弯曲的高光。例如,查看真实的 Quartz Composer UI,

真正的 Quartz Composer 用户界面。

我一直在尝试使用一种基于CGContextReplacePathWithStrokedPath(). 我的目标是绘制弯曲路径(顶部突出显示),将路径转换为“描边路径”,然后用渐变填充生成的路径。但是,当我尝试这样做时,这种方法(至少是我的代码)实际上并没有绘制任何东西。

一些示例代码来显示该方法。请注意,该CGPathCallback函数来自NSBezierPath+MCAdditions(我找不到代码的原始作者,但如果您搜索它会在很多地方出现)。

- (void)drawRect:(NSRect)dirtyRect
{
    /* Make any line you like */
    CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
    CGMutablePathRef centerline = CGPathCreateMutable();
    CGContextSetLineWidth(context, 10.);
    CGPathMoveToPoint(centerline, NULL, NSMinX(dirtyRect), NSMidY(dirtyRect));
    CGPathAddLineToPoint(centerline, NULL, NSMaxX(dirtyRect), NSMidY(dirtyRect));
    CGContextAddPath(context, centerline);

    /* Make a line "fill-able" */
    CGContextReplacePathWithStrokedPath(context);

    /* Clip to this line (maybe not required?)*/
    CGContextClip(context);

    /* Convert to a NSBezierPath */
    NSBezierPath *centrePath = [NSBezierPath bezierPath];
    CGPathApply(centerline, (__bridge void *)(centrePath), CGPathCallback);

    /* Finally fill the line with the gradient */
    NSGradient *lineGradient = [[NSGradient alloc] initWithStartingColor:[NSColor redColor] endingColor:[NSColor greenColor]];
    [lineGradient drawInBezierPath:centrePath angle:-90];
}

:沿着曲线绘制这样的高光最好的方法是什么,你会选择这种方法吗(这实际上不起作用!)?

4

1 回答 1

5

实现您想要的效果的一种方法是使用贝塞尔路径缠绕规则。按照您的示例,此代码有效:

NSBezierPath* path = [ NSBezierPath bezierPathWithRoundedRect: dirtyRect xRadius: 5 yRadius: 5 ];
dirtyRect = NSInsetRect( dirtyRect, 2, 2 );
[ path appendBezierPathWithRoundedRect: dirtyRect xRadius: 3 yRadius: 3 ];
[ path setWindingRule: NSEvenOddWindingRule ];

/* Finally fill the line with the gradient */
NSGradient *lineGradient = [[NSGradient alloc] initWithStartingColor:[NSColor redColor] endingColor:[NSColor greenColor]];
[lineGradient drawInBezierPath:path angle:-90];

NSevenOddWindingRule 允许您在未绘制的路径上打一个洞。为了达到最终效果,您可以将渐变从半透明白色变为完全透明的白色,并根据矩形的大小计算所需的端点。例如,这与您的原始图像接近:

NSBezierPath* path = [ NSBezierPath bezierPathWithRoundedRect: dirtyRect xRadius: 5 yRadius: 5 ];
dirtyRect = NSInsetRect( dirtyRect, 2, 2 );
[ path appendBezierPathWithRoundedRect: dirtyRect xRadius: 3 yRadius: 3 ];
[ path setWindingRule: NSEvenOddWindingRule ];

/* Finally fill the line with the gradient */
CGFloat heightOfHilight = 8;
CGFloat endLocation = heightOfHilight / dirtyRect.size.height;
NSGradient *lineGradient = [[NSGradient alloc] initWithColorsAndLocations:
        [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.5], 0.0,
        [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.0], endLocation,
        nil ];
[lineGradient drawInBezierPath:path angle:-90];
于 2013-02-24T03:18:08.423 回答