Как нарисовать размытую форму? - PullRequest
5 голосов
/ 04 июня 2011

Как нарисовать размытую фигуру в какао?Представьте себе тень с blurRadius, сопровождающим заполненный путь, но без формы контура переднего плана с острыми краями.

Я попытался использовать заполненный путь с тенью и установить прозрачный цвет заливки (0.0).Но это также делает тень невидимой, поскольку она, очевидно, учитывает альфа-объект "отбрасывания" тени.

Ответы [ 2 ]

5 голосов
/ 05 июня 2011

Это на самом деле довольно сложно.Я боролся с этим некоторое время, пока не нашел эту категорию на NSShadow:

@implementation NSShadow (Extras)

//draw a shadow using a bezier path but do not draw the bezier path
- (void)drawUsingBezierPath:(NSBezierPath*) path alpha:(CGFloat) alpha
{
    [NSGraphicsContext saveGraphicsState];
    //get the bounds of the path
    NSRect bounds = [path bounds];

    //create a rectangle that outsets the size of the path bounds by the blur radius amount
    CGFloat blurRadius = [self shadowBlurRadius];
    NSRect shadowBounds = NSInsetRect(bounds, -blurRadius, -blurRadius);

    //create an image to hold the shadow
    NSImage* shadowImage = [[NSImage alloc] initWithSize:shadowBounds.size];

    //make a copy of the shadow and set its offset so that when the path is drawn, the shadow is drawn in the middle of the image
    NSShadow* aShadow = [self copy];
    [aShadow setShadowOffset:NSMakeSize(0, -NSHeight(shadowBounds))];

    //lock focus on the image
    [shadowImage lockFocus];

    //we want to draw the path directly above the shadow image and offset the shadow so it is drawn in the image rect
    //to do this we must translate the drawing into the correct location
    NSAffineTransform* transform=[NSAffineTransform transform];
    //first get it to the zero point
    [transform translateXBy:-shadowBounds.origin.x yBy:-shadowBounds.origin.y];

    //now translate it by the height of the image so that it draws outside the image bounds
    [transform translateXBy:0.0 yBy:NSHeight(shadowBounds)];
    NSBezierPath* translatedPath = [transform transformBezierPath:path];

    //apply the shadow
    [aShadow set];

    //fill the path with an arbitrary black color
    [[NSColor blackColor] set];
    [translatedPath fill];
    [aShadow release];
    [shadowImage unlockFocus];

    //draw the image at the correct location relative to the original path
    NSPoint imageOrigin = bounds.origin;
    imageOrigin.x = (imageOrigin.x - blurRadius) + [self shadowOffset].width;
    imageOrigin.y = (imageOrigin.y - blurRadius) - [self shadowOffset].height;

    [shadowImage drawAtPoint:imageOrigin fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:alpha];
    [shadowImage release];
    [NSGraphicsContext restoreGraphicsState];
}

@end
2 голосов
/ 29 июня 2011

Я нашел одну реализацию, которая делает именно то, что я имел в виду онлайн.Автор Шон Патрик О'Брайен.Это категория на NSBezierPath, например:

@interface NSBezierPath (MCAdditions)

- (void)drawBlurWithColor:(NSColor *)color radius:(CGFloat)radius;

@end

@implementation NSBezierPath (MCAdditions)

- (void)drawBlurWithColor:(NSColor *)color radius:(CGFloat)radius
{
    NSRect bounds = NSInsetRect(self.bounds, -radius, -radius);
    NSShadow *shadow = [[NSShadow alloc] init];
    shadow.shadowOffset = NSMakeSize(0, bounds.size.height);
    shadow.shadowBlurRadius = radius;
    shadow.shadowColor = color;
    NSBezierPath *path = [self copy];
    NSAffineTransform *transform = [NSAffineTransform transform];
    if ([[NSGraphicsContext currentContext] isFlipped])
        [transform translateXBy:0 yBy:bounds.size.height];
    else
        [transform translateXBy:0 yBy:-bounds.size.height];
    [path transformUsingAffineTransform:transform];

    [NSGraphicsContext saveGraphicsState];

    [shadow set];
    [[NSColor blackColor] set];
    NSRectClip(bounds);
    [path fill];

    [NSGraphicsContext restoreGraphicsState];

    [path release];
    [shadow release];
}

@end

Этот код можно загрузить из этого сообщения в блоге Я не нашел его отдельно как код где-либо в Интернете.

...