logo头像

小玉的技术博客

Quartz2D编程之阴影

阴影是在图形对象下面绘制并有一定偏移的图像,用于模拟光源照射到图形对象上所形成的阴影效果,如图7-1所示。 文字也可以被遮蔽。 阴影可以使图像呈现出三维效果,或者像浮动一样。


阴影有三个属性:

1. x偏移量,用于指定阴影相对于图片在水平方向上的偏移值。
2. y偏移量,用于指定阴影相对于图片在竖直方向上的偏移值。
3. 模糊(blur)值,用于指定图像是否具有硬边缘(如图7-2左侧所示)或漫反射边缘(如图的右侧所示)。

本章将描述阴影是如何工作的及如何用Quartz 2D API来创建阴影。

阴影是如何工作的

Quartz中的阴影是图形状态的一部分。 您调用函数CGContextSetShadow来设置阴影,传递一个图形上下文,偏移量值和一个模糊值。 设置阴影后,您绘制的任何对象都会在设备RGB颜色空间中绘制一个具有1/3 alpha值的黑色阴影。 换句话说,阴影是用RGBA值{0, 0, 0, 1.0/3.0}设置的。

通过调用函数CGContextSetShadowWithColor可以绘制彩色阴影,并传递图形上下文,偏移值,模糊值和CGColor对象。颜色值依赖于颜色空间。

如果在调用CGContextSetShadow或CGContextSetShadowWithColor之前保存图形状态,我们可以通过恢复图形状态来关闭阴影。我们也可以通过设置阴影颜色为NULL来关闭阴影。

基于图形上下文的阴影绘制惯例

偏移值指定了阴影相对于相关图像的位置。这些偏移值由图形上下文来描述,并用于计算阴影的位置:

* 一个正值的x偏移表示阴影位于图形对象的右侧。
* 在Mac OS X中,正值的y偏移表示向上位移。 这与Quartz 2D的默认坐标系相匹配。
* 在iOS中,如果您的应用程序使用Quartz 2D API创建PDF或位图上下文,则正值得y偏移表示向上位移。
* 在iOS中,如果图形上下文是由UIKit创建的,例如由UIView对象创建的图形上下文或通过调用UIGraphicsBeginImageContextWithOptions函数创建的上下文,则正值得y偏移表示向下位移。 这符合UIKit坐标系统的绘图惯例。
* 阴影绘制约定不受CTM(当前变换矩阵)的影响。

绘制阴影

按照如下步骤来绘制阴影

1. 保存图形状态
2. 调用函数CGContextSetShadow,传递相应的值
3. 使用阴影绘制所有的对象
4. 恢复图形状态

按照如下步骤来绘制彩色阴影

1. 保存图形状态
2. 创建一个CGColorSpace对象,确保Quartz能正确地解析阴影颜色
3. 创建一个CGColor对象来指定阴影的颜色
4. 调用CGContextSetShadowWithColor,并传递相应的值
5. 使用阴影绘制所有的对象
6. 恢复图形状态

图7-3显示了两个带有阴影的矩形,其中一个是彩色阴影。

清单7-1中的函数显示了如何设置阴影来绘制如图7-3所示的矩形。 列表后面会出现每行代码的详细说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void MyDrawWithShadows (CGContextRef myContext, // 1
CGFloat wd, CGFloat ht);
{
CGSize myShadowOffset = CGSizeMake (-15, 20);// 2
CGFloat myColorValues[] = {1, 0, 0, .6};// 3
CGColorRef myColor;// 4
CGColorSpaceRef myColorSpace;// 5
CGContextSaveGState(myContext);// 6
CGContextSetShadow (myContext, myShadowOffset, 5); // 7
// Your drawing code here// 8
CGContextSetRGBFillColor (myContext, 0, 1, 0, 1);
CGContextFillRect (myContext, CGRectMake (wd/3 + 75, ht/2 , wd/4, ht/4));
myColorSpace = CGColorSpaceCreateDeviceRGB ();// 9
myColor = CGColorCreate (myColorSpace, myColorValues);// 10
CGContextSetShadowWithColor (myContext, myShadowOffset, 5, myColor);// 11
// Your drawing code here// 12
CGContextSetRGBFillColor (myContext, 0, 0, 1, 1);
CGContextFillRect (myContext, CGRectMake (wd/3-75,ht/2-100,wd/4,ht/4));
CGColorRelease (myColor);// 13
CGColorSpaceRelease (myColorSpace); // 14
CGContextRestoreGState(myContext);// 15
}

代码解释如下:

1. 需要三个参数 - 构建矩形时使用的图形上下文和宽度和高度。
2. 声明并创建一个包含阴影偏移值的CGSize对象。这些值指定对象左侧15个单位的阴影偏移量,以及对象上方20个单位的阴影偏移量。
3. 声明一个颜色值的数组。这个例子使用RGBA,但是这些值只有在它们被传递给Quartz以及Quartz才能正确解释值所需的色彩空间之前,才会有任何意义。
4. 声明存储的颜色参考。
5. 声明存储的颜色空间参考。
6. 保存当前的图形状态,以便以后恢复。
7. 将阴影设置为具有先前声明的偏移值,并将模糊值设置为5,表示柔和的阴影边缘。阴影将显示为灰色,其RGBA值为{0,0,0,1 / 3}。
8. 接下来的两行代码绘制了图7-3右侧的矩形。您用自己的绘图代码替换这些行。
9. 创建一个设备RGB颜色空间。创建CGColor对象时,您需要提供一个颜色空间。
1. 创建一个CGColor对象,提供设备RGB颜色空间和之前声明的RGBA值。这个对象指定了阴影颜色,在这种情况下是红色的,其值为0.6。
2. 设置一个颜色阴影,提供刚刚创建的红色。阴影使用之前创建的偏移量和5的模糊值,这表示柔和的阴影边缘。
3. 接下来的两行代码绘制图7-3左侧的矩形。您用自己的绘图代码替换这些行。
4. 释放颜色对象,因为它不再需要。
5. 释放颜色空间对象,因为它不再需要。
6. 将图形状态恢复到设置阴影之前的状态。
支付宝打赏 微信打赏

赞赏是不耍流氓的鼓励