阴影

阴影

如同人在太阳的倒影一样,那么阴影就模拟光源照射到图形对象上所形成的阴影效果。有时候可能需要一种悬浮的效果,那么就可以使用阴影。

如何设置阴影

  • 使用CGContextSetShadow设置阴影
  • 绘制图形,阴影就会自动呈现
1
2
3
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetShadow(context, CGSizeMake(10.0, 10.0), 0.1);
CGContextFillRect(context, CGRectMake(100.0, 100.0, 100.0, 100.0));

Shadow

注意点

  1. CGContextSetShadow 一定要先设置,先设置,先设置。不然是没有效果的。
  2. 与Context State 结合使用,是为了不对其他绘图有影响,只作用于该绘图,即关闭了阴影。

    1
    2
    CGContextSaveGState(context);
    CGContextRestoreGState(context);

阴影属性

阴影属性实际上就是CGContextSetShadow函数的三个参数的使用。

属性 类型 描述
c CGContextRef 上下文
offset CGSize 偏移量 根据坐标系而定在什么方向
blur CGFloat 模糊量 非负数 值越大越模糊

如何设置彩色阴影

  • 使用CGContextSetShadowWithColor传递相应的值
  • 绘制图形,彩色阴影就会自动呈现
1
2
3
4
5
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetShadowWithColor (context, CGSizeMake(10.0, 10.0), 5, [UIColor redColor].CGColor);
CGContextFillRect(context, CGRectMake(10.0, 400.0, 100.0, 100.0));
CGContextRestoreGState(context);

Shadow

彩色阴影属性

就比阴影属性CGContextSetShadow多了一个CGColor颜色对象

属性 类型 描述
color CGColorRef 色彩

颜色空间

使用Quartz中的CGColorCreate创建颜色。记得一定有创建就要有释放。因此需要调用CGColorReleaseCGColorSpaceRelease进行释放。

1
2
3
4
5
6
7
8
9
10
11
const CGFloat components[] = {1.0, 0.0, 0.0, 0.6};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef color = CGColorCreate(colorSpace, components);
CGContextSetShadowWithColor(context, CGSizeMake(10.0, 10.0), 5, color);
CGContextFillRect(context, CGRectMake(210.0, 100.0, 100.0, 100.0));
CGColorRelease (color);
CGColorSpaceRelease (colorSpace);
CGContextRestoreGState(context);

Shadow

CALayer

还可以通过UIView的layer属性设置阴影。

1
2
3
4
5
6
7
8
9
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
view.backgroundColor = [UIColor redColor];
view.layer.shadowColor = [UIColor redColor].CGColor;
view.layer.shadowOffset = CGSizeZero;
view.layer.shadowOpacity = 0.5;
view.layer.shadowRadius = 10;
[self addSubview:view];
属性 类型 描述
shadowColor CGColorRef 色彩
shadowOffset CGSize 偏移量,CGSizeZero四边都有阴影
shadowOpacity float 阴影的透明度
shadowRadius CGFloat 阴影的半径

关于QuartzCALayer偏移量

CALayerQuartz的阴影height方向不一样。

偏移量 方式 描述
height CALayer 正数在上方
height Quartz 正数在下方

实际案例 给圆角头像设置阴影

看上去很简单,先给头像设置圆角,在设置阴影。

1
2
3
4
5
6
7
8
9
10
11
CGRect avatarImageViewRect = CGRectMake(100, 100, 100, 100);
UIImageView *avatarImageView = [[UIImageView alloc] initWithFrame:avatarImageViewRect];
avatarImageView.image = [UIImage imageNamed:@"avatar"];
avatarImageView.layer.shadowColor = [UIColor redColor].CGColor;
avatarImageView.layer.shadowOffset = CGSizeZero;
avatarImageView.layer.shadowOpacity = 0.8;
avatarImageView.layer.shadowRadius = 10;
avatarImageView.layer.masksToBounds = YES;
avatarImageView.layer.cornerRadius = 10.0;
[avatarImageView addSubview:avatarImageView];
[self addSubview:avatarImageView];

Shadow

但是因为masksToBounds属性会把阴影也一同剪切掉了。所以是看不见阴影的。

  • 设置头像为圆角
  • 把头像加入到一个View中,为View添加阴影
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CGRect viewRect = CGRectMake(100, 100, 100, 100);
UIView *shadowView = [[UIView alloc] initWithFrame:viewRect];
shadowView.layer.shadowColor = [UIColor redColor].CGColor;
shadowView.layer.shadowOffset = CGSizeZero;
shadowView.layer.shadowOpacity = 0.8;
shadowView.layer.shadowRadius = 10;
shadowView.clipsToBounds = NO;
UIImageView *avatarImageView = [[UIImageView alloc] initWithFrame:shadowView.bounds];
avatarImageView.image = [UIImage imageNamed:@"avatar"];
avatarImageView.layer.masksToBounds = YES;
avatarImageView.layer.cornerRadius = 10.0;
[shadowView addSubview:avatarImageView];
[self addSubview:shadowView];

Shadow

实际上有多种实现方式,上面是新增一个UIView,也可以新增一个CALayer

性能

上面这种最简单的添加阴影的方法是存在性能问题的,特别是UITableViewCell做一些动画,你可能就会发现不流畅,卡顿。因为计算阴影需要Core Animation做一个离屏渲染,以View准确的形状确定清楚如何呈现其阴影。
只要你提前告诉CoreAnimation你要渲染的View的形状Shape,就会减少离屏渲染计算。

1
2
shadowView.layer.shadowPath =
[UIBezierPath bezierPathWithRect:shadowView.bounds].CGPath;

参考

  1. Quartz 2D Programming Guide

源代码

Quartz2D

坚持原创技术分享,您的支持将鼓励我继续创作!