2011-06-03 71 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下载。我没有在网上任何地方单独找到代码。