Quartz 2D编程指南 (九) —— 阴影(一)

版本记录

版本号 时间
V1.0 2018.09.05

前言

Quartz 2D框架相信大家都知道,也都一直在使用。Quartz 2D的API是纯C语言的,它是一个二维绘图引擎,同时支持iOS和Mac系统。Quartz 2D的API来自于Core Graphics框架,数据类型和函数基本都以CG作为前缀,接下来几篇我们就一起来看一下这个框架。感兴趣可以看上面几篇文章。
1. Quartz 2D编程指南 (一) —— 简介(一)
2. Quartz 2D编程指南 (二) —— Quartz 2D概览(二)
3. Quartz 2D编程指南 (三) —— 图形上下文(三)
4. Quartz 2D编程指南 (四) —— Paths路径(一)
5. Quartz 2D编程指南 (五) —— Paths路径(二)
6. Quartz 2D编程指南 (六) —— 颜色和颜色空间(一)
7. Quartz 2D编程指南 (七) —— 变换(一)
8. Quartz 2D编程指南 (八) —— Patterns图案样式(一)

Shadows - 阴影

阴影是在图形对象下面绘制并偏移的图像,使得阴影模仿投射在图形对象上的光源的效果,如图7-1所示。 文本也可以有阴影。 阴影可以使图像看起来是三维的,或者就像浮动一样。

Figure 7-1 A shadow

阴影有三个特征:

  • x偏移量,指定阴影从图像偏移到水平方向的距离。
  • y偏移量,指定阴影在垂直方向上与图像偏移的距离。
  • 一个模糊值,指定图像是否具有硬边缘(如图7-2左侧所示)或漫反射边缘(如图右侧所示)。

本章介绍阴影的工作原理,并说明如何使用Quartz 2D API创建阴影。

Figure 7-2 A shadow with no blur and another with a soft edge

How Shadows Work - 阴影工作原理

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

您可以通过调用CGContextSetShadowWithColor函数绘制彩色阴影,传递图形上下文,偏移值,模糊值和CGColor对象。 要为颜色提供的值取决于要绘制的颜色空间。

如果在调用CGContextSetShadowCGContextSetShadowWithColor之前保存图形状态,则可以通过恢复图形状态来关闭阴影。 您还可以通过将阴影颜色设置为NULL来禁用阴影。


Shadow Drawing Conventions Vary Based on the Context - 阴影绘制约定基于上下文变化

前面描述的偏移量指定阴影所在的位置与投射阴影的图像相关。 这些偏移由上下文解释并用于计算阴影的位置:

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

Painting with Shadows - 绘制阴影

按照以下步骤绘制阴影:

  • 1) 保存图形状态。
  • 2) 调用函数CGContextSetShadow,传递适当的值。
  • 3) 执行要应用阴影的所有绘图。
  • 4) 恢复图形状态。

按照以下步骤绘制彩色阴影:

  • 1) 保存图形状态。
  • 2) 创建CGColorSpace对象以确保Quartz正确解释阴影颜色值。
  • 3) 创建一个CGColor对象,指定要使用的阴影颜色。
  • 4) 调用函数CGContextSetShadowWithColor,传递适当的值。
  • 5) 执行要应用阴影的所有绘图。
  • 6) 恢复图形状态。

图7-3中的两个矩形用阴影绘制 - 一个带有彩色阴影。

Figure 7-3 A colored shadow and a gray shadow

Listing 7-1中的函数显示了如何设置阴影以绘制图7-3中所示的矩形。 列表后面会显示每个编号行代码的详细说明。

// Listing 7-1  A function that sets up shadows

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对象时需要提供颜色空间。
  • 10) 创建一个CGColor对象,提供设备RGB颜色空间和先前声明的RGBA值。此对象指定阴影颜色,在本例中为红色,alpha值为0.6。
  • 11) 设置颜色阴影,提供刚刚创建的红色。阴影使用先前创建的偏移量和模糊值5,表示软阴影边缘。
  • 12) 接下来的两行代码在图7-3的左侧绘制矩形。您可以使用自己的绘图代码替换这些行。
  • 13) 释放颜色对象,因为不再需要它。
  • 14) 释放颜色空间对象,因为不再需要它。
  • 15) 将图形状态恢复为设置阴影之前的状态。

后记

本篇主要讲述了阴影,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容