苹果公司在iOS和OS X上向开发者提供了强大的框架来处理图形和动画,这些框架和技术有:
UIKit:高层次的框架,允许开发人员创建视图、窗口、按钮和其他UI相关的组件。它还将一些低级别的API引入到易于使用的高级别的API中。
Quartz 2D:iOS上绘图的主要引擎,UIKit就使用Quartz。
Core Graphics:它支持图形上下文、加载图像、绘制图像,等等。
Core Animation:iOS上实现动画的框架。
1 绘制文本
public func drawAtPoint(point: CGPoint, withAttributes attrs: [String : AnyObject]?)
public func drawInRect(rect: CGRect, withAttributes attrs: [String : AnyObject]?)
override func drawRect(rect: CGRect) { let string: NSString = "Some String"; let attr: [String: AnyObject] = [NSFontAttributeName: UIFont.init(name: "HelveticaNeue-Bold", size: 30)!, NSForegroundColorAttributeName: UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0), NSBackgroundColorAttributeName: UIColor.lightGrayColor()] string.drawAtPoint(CGPointMake(40, 180), withAttributes: attr) let string2: NSString = "I Learn Really Fast" string2.drawInRect(CGRectMake(40, 250, 100, 100), withAttributes: attr) }
2 绘制图形
UIKit帮助你轻松的绘制图像,你所需要做的是需要把你的图像加载在UIImage类的实例中。UIImage类提供了各种类方法和实例方法来加载图像。
public func drawAtPoint(point: CGPoint)
public func drawInRect(rect: CGRect)
override func drawRect(rect: CGRect) {
let image = UIImage(named: "f015")
image?.drawAtPoint(CGPointMake(40, 80)) //按照图片的原始大小绘制
let image2 = UIImage(named: "f015")
image2?.drawInRect(CGRectMake(40, 200, 10, 10)) //在矩形区域内绘制
}
3 绘制线条
路径是由屏幕上一个或一系列点构成。路径和线条有很大的区别,路径可以包含很多线条,但线条不能包含很多路径。把路径当做一系列的点,就是这么简单。
必须使用路径来绘制线条。指定起点和终点,然后要求Core Graphics来绘制路径。
绘制线条的步骤:
(1)为图形上下文选定一个颜色;
(2)使用UIGraphicsGetCurrentContext函数获取图形上下文句柄;
(3)使用CGContextSetLineWidth设置线条的宽度;
(4)使用CGContextMoveToPoint过程设置线条的起点;
(5)使用CGContextAddLineToPoint过程在图形上下文移动画笔来设置线条的终点;
(6)使用CGContextStrokePath过程创建已设置好的路径。
override func drawRect(rect: CGRect) { UIColor.blueColor().set() let context = UIGraphicsGetCurrentContext() CGContextSetLineWidth(context, 5.0)
//.Miter:尖角,默认样式 .Round:圆角 .Bevel:平角 CGContextSetLineJoin(context, CGLineJoin.Round)
CGContextMoveToPoint(context, 40, 80)
CGContextAddLineToPoint(context, 80, 160)
CGContextAddLineToPoint(context, 120, 80)
CGContextStrokePath(context)
}
4 绘制路径
路径属于正在绘制他们的图形上下文。路径没有边界(Boundary)或特定的形状,但路径有边界框(Boundary boxes)。Boundary和Boundary Boxes完全不一样,Boundary限制你在画布上哪些不可以用来绘画,而Boundary Boxes是包含了所有路径上的形状、点和其他已经绘制的对象额最小矩形。你可以在图形上下文中对路径进行填充,或者对它进行描边。下面是你会用到的一些方法:
(1)CGPathCreateMutable函数:创建一个类型为CGMutablePathRef的可变路径,并返回其句柄。每次使用完这个路径,我们都应该为其做善后工作。
(2)CGPathMoveToPoint过程:在路径上移动当前的位置到一个点。
(3)CGPathAddLineToPoint过程:从当前的画笔位置向指定位置绘制线条。
(4)CGContextAddPath过程:添加一个路径到图形上下文。
(5)CGContextDrawPath过程:在图形上下文绘制给出的路径。
(6)CGPathRelease过程:释放为路径句柄分配的内存。(ARC环境下不需要自己手动释放,系统会自己释放)
(7)CGPathAddRect过程:向路径添加一个矩形。
(8)kCGPathStroke:使用当前选定的描边颜色为路径描边。
(9)kCGPathFill:使用当前选定的颜色填充路径所包围的区域。
(10)kCGPathFillStroke:组合描边和填充。
override func drawRect(rect: CGRect) { let path: CGMutablePathRef = CGPathCreateMutable() CGPathMoveToPoint(path, nil, rect.origin.x, rect.origin.y) CGPathAddLineToPoint(path, nil, rect.size.width, rect.size.height) CGPathMoveToPoint(path, nil, rect.size.width, rect.origin.y) CGPathAddLineToPoint(path, nil, rect.origin.x, rect.size.height) let context = UIGraphicsGetCurrentContext() CGContextAddPath(context, path) UIColor.brownColor().setStroke() CGContextDrawPath(context, CGPathDrawingMode.Stroke) } override func drawRect(rect: CGRect) { let path: CGMutablePathRef = CGPathCreateMutable() CGPathMoveToPoint(path, nil, 40, 80) CGPathAddLineToPoint(path, nil, 100, 150) CGPathAddLineToPoint(path, nil, 120, 100) CGPathAddLineToPoint(path, nil, 40, 80) let context = UIGraphicsGetCurrentContext() CGContextAddPath(context, path) UIColor.redColor().setStroke() UIColor.blueColor().setFill() CGContextDrawPath(context, CGPathDrawingMode.FillStroke) }
5 绘制矩形
override func drawRect(rect: CGRect) { let path: CGMutablePathRef = CGPathCreateMutable() CGPathAddRect(path, nil, CGRectMake(40, 80, 100, 100)) //绘制一个矩形
CGPathAddRects(path, nil, [CGRectMake(40, 80, 100, 100), CGRectMake(40, 200, 100, 100)], 2) //可以绘制多个矩形
let context = UIGraphicsGetCurrentContext() CGContextAddPath(context, path) UIColor.brownColor().setStroke() UIColor.redColor().setFill() CGContextSetLineWidth(context, 5.0) CGContextDrawPath(context, CGPathDrawingMode.FillStroke) }
6 为形状添加阴影
(1)CGContextSetShadow:将会创建黑色或灰色阴影
(2)CGContextSetShadowWithColor:可以自己设置阴影的颜色
override func drawRect(rect: CGRect) { let context = UIGraphicsGetCurrentContext() CGContextSetShadow(context, CGSizeMake(5, 5), 3.0) // CGContextSetShadowWithColor(context, CGSizeMake(5, 5), 3.0, UIColor.lightGrayColor().CGColor) let path: CGMutablePathRef = CGPathCreateMutable() CGPathAddRect(path, nil, CGRectMake(40, 80, 100, 100)) CGContextAddPath(context, path) UIColor(red: 0.2, green: 0.6, blue: 0.8, alpha: 1.0).setFill() CGContextDrawPath(context, CGPathDrawingMode.Fill) }
7 创建和绘制渐变
override func drawRect(rect: CGRect) { let context = UIGraphicsGetCurrentContext() CGContextSaveGState(context) let colorSpace: CGColorSpaceRef? = CGColorSpaceCreateDeviceRGB() //蓝色作为起点 let startColor = UIColor.blueColor() let startColorComponents = CGColorGetComponents(startColor.CGColor) //橘色作为终点 let closeColor = UIColor.orangeColor() let closeColorComponents = CGColorGetComponents(closeColor.CGColor) let colorComponents = [startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3], closeColorComponents[0], closeColorComponents[1], closeColorComponents[2], closeColorComponents[3]] let colorIndices: [CGFloat] = [0.0, 1.0] let gradient = CGGradientCreateWithColorComponents(colorSpace, colorComponents, colorIndices, 2) //起点 let startPoint = CGPointMake(80.0, 80.0) //终点 let closePoint = CGPointMake(250.0, 80.0) //.DrawsAfterEndLocation:扩展整个渐变到渐变的终点之后的所有点 //.DrawsBeforeStartLocation:扩展整个渐变到渐变的起点之前的所有点 CGContextDrawLinearGradient(context, gradient, startPoint, closePoint, [.DrawsAfterEndLocation, .DrawsBeforeStartLocation]) CGContextRestoreGState(context) }
8 平移图形上下文的形状
第一种方法:CGPathAddRect方法的第二个参数是一个CGAffineTransform类型的变换对象。
override func drawRect(rect: CGRect) { //平移图形上下文的形状//第一种方法:CGPathAddRect方法的第二个参数是一个CGAffineTransform类型的变换对象 let path = CGPathCreateMutable() let rectangle = CGRectMake(10, 80, 200, 300) var transform = CGAffineTransformMakeTranslation(100, 0) CGPathAddRect(path, &transform, rectangle) let context = UIGraphicsGetCurrentContext() CGContextAddPath(context, path) UIColor.purpleColor().setStroke() UIColor.blueColor().setFill() CGContextSetLineWidth(context, 5.0) CGContextDrawPath(context, .FillStroke)
}
第二种方法:通过CGContextTransformCTM过程对图形上下文应用变换,这将把一个平移变换应用到当前变换矩阵(CTM:current transformation matrix)。把CTM认为是它设置了你的图形上下文的中心,是它把你绘制的每个点投射到屏幕上。通过改变CTM的配置,强制把所有绘制在图形上下文的形状转移到画布上的另一个地方。
override func drawRect(rect: CGRect) {
//平移图形上下文的形状//第二种方法:通过CGContextTransformCTM过程对图形上下文应用变换,这将把一个平移变换应用到当前变换矩阵(CTM:current transformation matrix)。把CTM认为是它设置了你的图形上下文的中心,是它把你绘制的每个点投射到屏幕上。通过改变CTM的配置,强制把所有绘制在图形上下文的形状转移到画布上的另一个地方。 let path = CGPathCreateMutable() let rectangle = CGRectMake(10, 80, 200, 300) CGPathAddRect(path, nil, rectangle) let context = UIGraphicsGetCurrentContext() CGContextSaveGState(context) CGContextTranslateCTM(context, 100, 0) CGContextAddPath(context, path) CGContextSetLineWidth(context, 5.0) UIColor.purpleColor().setStroke() UIColor.blueColor().setFill()
CGContextDrawPath(context, .FillStroke)
}
9 缩放图形上下文的形状
同上两种方法。
第一种方法:var transform = CGAffineTransformMakeScale(1.0, 0.5)
第二种方法:CGContextScaleCTM(context, 1, 0.5)
10 旋转图形上下文的形状
同上两种方法。
第一种方法:var transform = CGAffineTransformMakeRotation(-CGFloat(M_2_PI)/2.0)
第二种方法:CGContextRotateCTM(context, -CGFloat(M_2_PI)/2.0)
11 动画--移动视图、缩放视图、旋转视图
在iOS上有各种方式可以实现动画:在一个较低的层次提供了这种能力,在更高的层次也提供这种能力。我们可以获得的最高层次的动画能力是通过UIKit。UIKit中包括一些Core Animation的较低层次的功能,并且包装成非常简洁的API供我们使用。
UIKit中实现动画的起点是调用UIView类的类方法beginAnimations:context:。其第一个参数是一个可选的动画的名字,第二个是一个可选的上下文,在之后传递给动画的委托方法时你可以获得它。
在你通过beginAnimations:context:方法开始一个动画之后,它实际上不会马上执行,而是直到你调用UIView类的commitAnimation类方法。在beginAnimation:context:和commitAnimation之间,你对一个视图对象的计算将在commitAnimation被调用之后开始进行动画。
使用UIKit执行动画时常用的方法:
(1)beginAnimations:context:开始一个动画块。调用这个类方法之后,你对视图任何动画属性的改变,都会在动画块提交之后形成动画。
(2)setAnimationDuration:以秒为单位设置动画的持续时间。
(3)setAnimationDelegate:设置一个对象来接受动画开始之前、动画期间或动画结束之后发生的各种事件的委托对象。设置一个委托对象不会立即开始发送动画委托消息。你必须对视图对象使用其他的setter方法来告诉UIKit你的委托对象中的哪个选择器(selector)要接受哪些委托消息。
(4)setAnimationDidStopSelector:设置动画完成时委托对象中用过被调用的方法。这个方法按照以下顺序接受是哪个参数:
- NSString类型的动画标识:它包含在动画开始时传给beginAnimations:context:方法的动画标识。
- 一个“已完成”的标识,NSNumber类型:此参数包含一个由NSNumber包装的布尔值,如果动画在被其他代码停止之前能够完整地执行,运行时(Runtime)将它设置为YES。如果这个值被设置为NO,意味着动画在完后之前被中断了。
- 一个void *类型的上下文:这是动画开始时传给beginAnimations:context:方法的上下文。
(5)setAnimationWillStartSeletor:设置动画即将开始时委托对象中被顶选择器,参数通上。
(6)setAnimationDelay: 设置一个动画启动的延迟时间。
(7)setAnimationRepeatCount:设置一个动画块需要重复它的动画次数。
UIView.beginAnimations("iconAnimation", context: nil) UIView.setAnimationDuration(3.0) //可以直接通过改变frame来移动视图 self.iconImage.frame = CGRectMake(UIScreen.mainScreen().bounds.width - 100, UIScreen.mainScreen().bounds.height - 100, 100, 100) //缩放视图--缩放后,视图的中心不变 self.iconImage.layer.setAffineTransform(CGAffineTransformMakeScale(2.0, 2.0)) //旋转视图 self.iconImage.layer.setAffineTransform(CGAffineTransformMakeRotation(CGFloat(M_PI))) UIView.commitAnimations()