3

Quartz composer の patch オブジェクトのようなカスタム ビューをいじってみました。私の偽の Quartz Composer ビューは十分に見栄えがします。これは、2 つの異なる線形グラデーション、影、上部に 1 つのハイライト ラインを持つ単一のビューです。

偽の Quartz Composer UI。

これを拡張して角を丸くしたいと思います。これはグラデーションなどでは非常に簡単ですが、ビューの上部に沿って曲線のハイライトを描画する方法がわかりません。たとえば、実際の Quartz Composer UI を参照してください。

Real Quartz Composer UI。

に基づいたアプローチを使用しようとしていますCGContextReplacePathWithStrokedPath()。私の目標は、曲線のパス (上部のハイライト) を描画し、パスを「ストローク パス」に変換してから、結果のパスをグラデーションで塗りつぶすことです。ただし、このアプローチ (少なくとも私のコード) は、これを試みても実際には何も描画しません。

メソッドを示すサンプルコード。関数はNSBezierPath+MCAdditionsから来ていることに注意してください(コードの元の作成者は見つかりませんが、検索すると多くの場所で見つかります)。CGPathCallback

- (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];
}

Q.曲線に沿ってこのようなハイライトを描画する最良の方法は?

4

1 に答える 1

5

必要な効果を実現する 1 つの方法は、ベジェ パスのワインディング ルールを使用することです。あなたの例に従って、このコードは機能します:

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 に答える