Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw drop-down shadows in iOS

Tags:

iphone

A CAShapeLayer uses a CGPathRef to draw it's stuff. So I have a star path, and I want a smooth drop shadow with a radius of about 15 units. Probably there is some nice functionality in some new iPhone OS versions, but I need to do it myself for a old aged version of 3.0 (which most people still use).

I tried to do some REALLY nasty stuff: I created a for-loop and sequentially created like 15 of those paths, transform-scaling them step by step to become bigger. Then assigning them to a new created CAShapeLayer and decreasing it's alpha a little bit on every iteration. Not only that this scaling is mathematically incorrect and sucks (it should happen relative to the outline!), the shadow is not rounded and looks really ugly. That's why nice soft shadows have a radius.

The tips of a star shouldn't appear totally sharp after a shadow size of 15 units. They should be soft like cream. But in my ugly solution they're just as s harp as the star itself, since all I do is scale the star 15 times and decrease it's alpha 15 times. Ugly.

I wonder how the big guys do it? If you had an arbitrary path, and that path must throw a shadow, how does the algorithm to do that work? Probably the path would have to be expanded like 30 times, point-by-point relative to the tangent of the outline away from the filled part, and just by 0.5 units to have a nice blending.

Before I re-invent the wheel, maybe someone has a handy example or link?

like image 840
dontWatchMyProfile Avatar asked May 28 '10 16:05

dontWatchMyProfile


1 Answers

A shadow is a translucent grayscale mask of the shape of an object blurred and offset.

CGContextSetShadowWithColor and CGContextSetShadow are how this is done on iPhone. You set the shadow then draw something and a shadow is also applied.

A CAShapeLayer does not have an easy option to apply a shadow. You will have to create a custom view or layer and set the shadow before drawing your shape.

I have not tried it, but the following might work:

@interface ShadowShapeLayer : CAShapeLayer
@end

@implementation ShadowShapeLayer
-(void) drawInContext:(CGContextRef)context {
  CGContextSaveGState( context );
  CGContextSetShadow( context , CGSizeMake( 5 , 5 ) , 15 );
  [super drawInContext:context];
  CGContextRestoreGState( context );
}
@end

Edit: Thanks Miser.

like image 173
drawnonward Avatar answered Oct 19 '22 10:10

drawnonward