2011-06-03 68 views
5

如何在可可中繪製模糊的形狀?想象一下帶有填充路徑的blurRadius的陰影,但沒有尖銳的前景路徑形狀。如何繪製模糊的形狀?

我試過的是使用帶陰影的填充路徑,並將填充顏色設置爲透明(alpha 0.0)。但是這也使得這個影子不可見,因爲它顯然會將影子「對象」的影子考慮在內。

回答

5

這實際上是非常棘手的。我這個掙扎了一段時間,直到我用這一類的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

我找到了一個實現這不正是我在網上的意思。作者:肖恩帕特里克奧布萊恩。這是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 

這段代碼是從這個blog post下載。我沒有在網上任何地方單獨找到代碼。