如何在NSButton中绘制像图像一样的NSImage(具有深度)?

Flo*_*ked 18 cocoa objective-c draw nsimage

有没有办法在NSButtons或其他可可界面元素中绘制像图像的NSImage?

以下是示例: 在此输入图像描述 在此输入图像描述

Apple使用带有黑色图标的pdf: 在此输入图像描述

omz*_*omz 58

如果您只是想在按钮中使用自己的图像时应用此效果,请使用[myImage setTemplate:YES].没有内置方法可以在具有屏幕截图中显示的样式的按钮之外使用此效果绘制图像.

但是,您可以使用Core Graphics复制效果.如果仔细观察,效果包括水平渐变,白色阴影和暗阴影(后者是最难的).

您可以将其作为类别实现NSImage:

//NSImage+EtchedDrawing.h:
@interface NSImage (EtchedImageDrawing)    
- (void)drawEtchedInRect:(NSRect)rect;
@end

//NSImage+EtchedDrawing.m:
@implementation NSImage (EtchedImageDrawing)

- (void)drawEtchedInRect:(NSRect)rect
{
    NSSize size = rect.size;
    CGFloat dropShadowOffsetY = size.width <= 64.0 ? -1.0 : -2.0;
    CGFloat innerShadowBlurRadius = size.width <= 32.0 ? 1.0 : 4.0;

    CGContextRef c = [[NSGraphicsContext currentContext] graphicsPort];

    //save the current graphics state
    CGContextSaveGState(c);

    //Create mask image:
    NSRect maskRect = rect;
    CGImageRef maskImage = [self CGImageForProposedRect:&maskRect context:[NSGraphicsContext currentContext] hints:nil];

    //Draw image and white drop shadow:
    CGContextSetShadowWithColor(c, CGSizeMake(0, dropShadowOffsetY), 0, CGColorGetConstantColor(kCGColorWhite));
    [self drawInRect:maskRect fromRect:NSMakeRect(0, 0, self.size.width, self.size.height) operation:NSCompositeSourceOver fraction:1.0];

    //Clip drawing to mask:
    CGContextClipToMask(c, NSRectToCGRect(maskRect), maskImage);

    //Draw gradient:
    NSGradient *gradient = [[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.5 alpha:1.0]
                                                          endingColor:[NSColor colorWithDeviceWhite:0.25 alpha:1.0]] autorelease];
    [gradient drawInRect:maskRect angle:90.0];
    CGContextSetShadowWithColor(c, CGSizeMake(0, -1), innerShadowBlurRadius, CGColorGetConstantColor(kCGColorBlack));

    //Draw inner shadow with inverted mask:
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef maskContext = CGBitmapContextCreate(NULL, CGImageGetWidth(maskImage), CGImageGetHeight(maskImage), 8, CGImageGetWidth(maskImage) * 4, colorSpace, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(maskContext, kCGBlendModeXOR);
    CGContextDrawImage(maskContext, maskRect, maskImage);
    CGContextSetRGBFillColor(maskContext, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(maskContext, maskRect);
    CGImageRef invertedMaskImage = CGBitmapContextCreateImage(maskContext);
    CGContextDrawImage(c, maskRect, invertedMaskImage);
    CGImageRelease(invertedMaskImage);
    CGContextRelease(maskContext);

    //restore the graphics state
    CGContextRestoreGState(c);
}

@end
Run Code Online (Sandbox Code Playgroud)

视图中的示例用法:

- (void)drawRect:(NSRect)dirtyRect
{
    [[NSColor colorWithDeviceWhite:0.8 alpha:1.0] set];
    NSRectFill(self.bounds);

    NSImage *image = [NSImage imageNamed:@"MyIcon.pdf"];
    [image drawEtchedInRect:self.bounds];
}
Run Code Online (Sandbox Code Playgroud)

这会给你以下结果(以不同的大小显示): 截图

您可能需要尝试使用渐变颜色和两个阴影的偏移/模糊半径来更接近原始效果.

  • 此外,将"模板"(使用大写字母T)放在图像名称的末尾将产生相同的效果,代码更少(只需在IB中设置名称). (2认同)
  • 我使用与您上面发布的代码完全相同的代码,但是没有得到结果.图像本身和白色投影正确绘制,但暗阴影处于错误的位置.我能做什么? (2认同)