Apple recently made a big deal out of putting reflections on images. It looks great and it’s a nice little something-something but now everyone wants it and developers have to deliver. I haven’t seen a complete, end-to-end example in using pure Cocoa to put a reflection on an image so I figured I’d put something together.
NSImage *img = [[NSImage imageNamed:@"NSApplicationIcon"] copy]; // 1
NSSize s = [img size];
NSImage *final = [[NSImage alloc] initWithSize:NSMakeSize(s.width, s.height*2+1)]; // 2
[final lockFocus];
[img dissolveToPoint:NSMakePoint(0, s.height+1) fraction:1.0]; // 3
[[NSBezierPath bezierPathWithRect:NSMakeRect(0, 0, s.width, s.height)] fillGradientWithStartColor:[NSColor redColor] endColor:[NSColor clearColor]]; // 4
NSAffineTransform *t = [NSAffineTransform transform]; // 5
[t scaleXBy:1 yBy:-1];
[t concat];
[img drawAtPoint:NSMakePoint(0, -s.height) fromRect:NSZeroRect operation:NSCompositeSourceIn fraction:1.0]; // 6
[final unlockFocus];
[imageView setImage:final]; // 7
First, get your image. Here, I’m just grabbing the application’s icon. Note that I’m leaking memory in this example because, frankly, I just don’t care. It’s an example. Be sure to exercise good memory management when doing this in a real application.
Now we’re going to put our images together. Since were doing a full reflection, this image needs to be twice the height of the original.
Draw the original image in the top half of the image. The standard seems to have a one pixel span between original and reflection so that’s where that stray
1comes from.Get a simple color to clear gradient. Here, I’m using my own custom NSBezierPath category but there are numerous ones out there on the internet. Find something that produces a simple gradient and go with it. This will be the basis of the fade effect of the reflection.
For most original images, you can just call
setFlipped:instead of using a transform. This, however, won’t work for generated images. At least it didn’t work when I tried to draw a simple image in code. NSAffineTransform works for whatever I threw at it so I’m sticking with it.Use a
drawfunction to pick up the affine transform (my favorite,dissolveToPoint:won’t work right here). I’m also usingNSCompositeSourceInbecause it appears to work right.Now do something with your new image.
Leave a Reply