Quartz上下文支持阴影绘制作为可选的特定上下文功能。绘制在您指定的路径偏移处,阴影绘制模拟物理对象上光源的效果。图5-8演示了阴影在绘制到上下文时的外观。绘制阴影需要频繁的CPU计算,但是它们为你的界面增加了美丽的细节。
图5-8 您可以添加阴影到上下文
与所有其他上下文状态更改一样,阴影会影响任何后续绘制操作。如果要在应用阴影之后重置状态,请确保执行保存并恢复上下文图形状态(GState
)。设置阴影颜色为透明([UIColor clearColor].CGColor
)以“禁用”应用程序阴影。
清单5-10用Objective-C颜色参数包装CGContextSetShadowWithColor()
函数。您可以指定颜色,偏移量(大小)和模糊量。该函数更新上下文状态,应用这些值。关于阴影这里有几点需要知道的:
- 每个阴影以相对于任何绘图操作的x和y偏移量添加。你可以通过
CGSize
指定它。 - 浮点模糊参数指示硬(0)或软(大于0)的程度来绘制边缘。
- 您可以通过调用
CGContextSetShadow()
来跳过颜色值。此函数默认为半透明黑色,具有0.33 alpha值。清单5 - 10使用这种颜色,如果调用SetShadow()
则使用的是nil颜色参数。
清单5-10 Specifying a Context Shadow
1 | void SetShadow(UIColor *color, CGSize size, CGFloat blur) |
表5-1显示了阴影参数对绘图的影响。
Application | Result | Result |
---|---|---|
当存储到上下文状态时,阴影适用于任何绘图操作。您通过填充(左)和描边(右)创建阴影。 | ||
增加模糊半径可以柔化模糊。左图像使用模糊半径4.将其与右侧设置为0的硬模糊比较。硬阴影创建斜角和挤压效果,赋予形状3D外观。 | ||
您可以应用任何阴影颜色。这里的示例是紫色的。左图像使用0.5的alpha级别,右侧为1.0的alpha。 | ||
调整偏移量来移动影子。左图像将先前图像的阴影从(4,4)切换到(-4,4)。阴影向左移动,但保持在形状下。正确的图像使用(-4,-4)。 阴影出现在形状的左侧和顶部。 |
(绘制)阴影的代价
无可争辩的事实,阴影给你的绘图计算增加了高负荷。虽然视觉上华丽,它们不一定是您要用于实时高性能界面元素的功能。
只要有可能,在开发过程中分析你的绘图操作,以了解他们的成本。这里有一个quick-and-dirty的方法来使用,你建立你的方法,以跟踪已用时间:
1 | NSDate *start = [NSDate date]; // Perform drawing operations NSLog(@"%f seconds", [[NSDate date] timeIntervalSinceDate:start]); |
绘制内阴影
图5-9显示了通过用添加的内部阴影填充Bezier路径创建的图像。内部阴影,如名称所示,添加在路径的边界内绘制的阴影。取决于你的大脑如何处理它,在这一刻,阴影看起来好像外面的形状是投射的一个阴影,或者,如果你可以让你的头脑做一个触发器,形状表示一个浮雕的边缘。
图5-9可以创建带有内阴影的路径。
图5-10显示了组合创建内部阴影的绘图操作。第一个操作是无光泽填充操作。第二个操作是建立阴影,掩盖在形状内部。
图5-10左:原始路径。中间:反转路径。右:在路径边界内反转。
如清单5-9所示,构建阴影需要反转路径。允许上下文为该倒置形状绘制阴影,该阴影自然落在原始路径的剩余部分中。剪切上下文可确保在该路径之外不绘制任何内容。
清单5-11显示了绘制内部阴影的步骤。首先设置上下文阴影状态。此函数将此应用于GState
堆栈中,确保绘图操作后状态恢复。它还将绘图区域剪切到作为参数传递的路径。这确保所有绘图都在路径边界内发生。
接下来,它设置绘图颜色。由于所有绘图都是在剪辑区域外完成的,因此理论上任何非透明颜色都可以奏效。然而,在实践中,在路径边界经历高曲率时,您将遇到轻微的限幅误差。这是一个已知的问题。使用阴影颜色避免了视觉不连续。
最后,此函数用该颜色填充路径的反转。由于剪辑,创建的唯一的图形是阴影,它显示在图5-10的右侧。
清单5-11 绘制内阴影
1 | void DrawInnerShadow(UIBezierPath *path, |
清单5-12提供了另一个内部阴影。我称这种方法“PaintCode”解决方案,因为它最初的灵感来自PixelCut(http://pixelcut.com)从他们的PaintCode应用程序导出的代码。它比清单5-11中的解决方案更加繁琐,但它避免了边缘情况,它将反转路径填充颜色的小部分与高度变形曲线的绘制混合。它的工作原理是轻微地扭转反向路径,以削减一个微小的位,远离那边缘。这导致更清晰的阴影呈现。
清单5-12绘制(更好的)内部阴影
1 | - (void) drawInnerShadow: (UIColor *) color |
压花形状
在左下方应用一个黑色的内部阴影,在右上方应用一个浅色的内部阴影可以创建图5-11中所示的浮雕效果。这种效果使用柔和的模糊效果来创建平滑过渡:
1 | DrawInnerShadow(path, [[UIColor whiteColor] |
图5-11您可以将明暗的内部阴影结合起来,以“镶嵌”贝塞尔路径。
您可以将较柔和的内部阴影与尖锐的外部阴影结合起来,为您的形状创建一个斜角效果,如图5-12所示:
1 | DrawInnerShadow(bunny, WHITE_LEVEL(0, 0.5), |
图5-12通过组合内部阴影和外部阴影以及锐利的边缘来“斜切”(bevel)一条路径。
本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。