Cocoa provides support for shadows through the NSShadow class. A shadow mimics a light source cast on the object, making paths appear as if they’re floating above the surface of the view. Figure 8-1 shows the effect created by a shadow for a few paths.
A shadow effect consists of horizontal and vertical offset values, a blur value, and the shadow color. These effects combine to give the illusion that there is a light above the canvas that is shining down on the shapes below. The offset and blur values effectively determine the position of the light and the height of the shapes above the canvas.
Shadow positions always use the base coordinate system of the view, ignoring any transforms you apply to the shapes in your view. This means that no matter how you manipulate the shapes in a view, the apparent position of the light generating the shadows never changes. If you want to change the apparent position of the light, you must change the shadow object attributes and apply the updated shadow object to the current graphics context before drawing your content.
To create a shadow, you create an NSShadow object and call its methods to set the desired shadow attributes. If you anticipate one or more paths overlapping each other, you should be sure to choose a color that has an alpha value; otherwise, shadows that intersect other objects might look flat and ruin the effect. To apply the shadow, invoke its set method.
Listing 8-1 shows the code used to create the shadow for the paths in Figure 8-1. A partially transparent color is used to allow for overlapping paths and shadows.
Listing 8-1 Adding a shadow to a path
[NSGraphicsContext saveGraphicsState]; |
// Create the shadow below and to the right of the shape. |
NSShadow* theShadow = [[NSShadow alloc] init]; |
[theShadow setShadowOffset:NSMakeSize(10.0, -10.0)]; |
[theShadow setShadowBlurRadius:3.0]; |
// Use a partially transparent color for shapes that overlap. |
[theShadow setShadowColor:[[NSColor blackColor] |
colorWithAlphaComponent:0.3]]; |
[theShadow set]; |
// Draw your custom content here. Anything you draw |
// automatically has the shadow effect applied to it. |
[NSGraphicsContext restoreGraphicsState]; |
[theShadow release]; |
Shadow effects are stored as part of the graphics state, so once set, they affect all subsequent rendering commands in the current context. This is an important thing to remember because it might force you to think about the order in which you draw your content. For example, if you set up a shadow, fill a path, and then stroke the same path, you do not get a single shape with an outline, fill color, and shadow. Instead, you get two shapes—an outline and a fill shape—and two shadows, one for each shape. If you stroke the path after filling it, the shadow for the stroked path appears on top of the filled shape. In Figure 8-1, the desired effect was achieved by applying the shadow to only the fill shape of each path.
Note: Another way to a single shadow for multiple paths is using a Quartz transparency layer. For more information about using transparency layers, see Quartz 2D Programming Guide.
Last updated: 2007-10-31