图形图像及动画


图形图像及动画

内容概述

  • 字体和颜色
  • 绘制文本
  • 绘制图片
  • 划线
  • 画矩形
  • 移动动画
  • 缩放动画
  • 旋转动画

我们看到很多应用程序和游戏有漂亮的画面和动画效果,这些都离不开图形图像和动画编程。iOS SDK 对图形图像和动画的支持包括在如下的框架中:

  1. Quartz,该框架是一个强大的2D图形引擎,用来创建矢量图,位图和PDF等格式的内容。
  2. UIKit,UIKit使用Quartz来创建,主要提供系统上层UI界面,如窗口、按钮和标签等。
  3. Core Animation,该框架提供了视图的动画效果,如移动、旋转和缩放等。
  4. OpenGL ES,该框架提供了专门针对移动设备的3D图形引擎。

UIKit框架的内容在前面章节用户界面中已经讲述,本章重点讲述如何使用Quartz框架绘图,如何使用Core Animation框架创建动画效果以及字体和颜色的应用。

20.1 字体和颜色

为显示的文本内容设置合适的字体和颜色,对于文本内容的展示效果至关重要。在iOS SDK的UIKit框架中提供了字体和颜色的支持。字体类是UIFont颜色类是UIColor。

我们可以使用UIFont的+ (UIFont )fontWithName:(NSString )fontName size:(CGFloat)fontSize方法创建一个新字体,可以使用+ (UIFont )systemFontOfSize:(CGFloat)fontSize方法创建指定大小的系统字体,也可以使用+ (UIFont )boldSystemFontOfSize:(CGFloat)fontSize方法创建粗体系统字体。

使用UIFont的+ (NSArray )familyNames方法获得字体家族数组,也可以使用+ (NSArray )fontNamesForFamilyName:(NSString *)familyName方法获得字体数组。

下面通过一个案例来演示字体的用法,创建步骤如下:

  1. 创建一个项目,在界面上添加两个按钮,和4个标签组件,在.h头文件中添加两个按钮的点击事件方法和4个标签的属性。
@interface AmakerViewController : UIViewController

// 获得字体的属性

- (IBAction)get:(id)sender;

// 显示系统支持的字体家族名称

- (IBAction)display:(id)sender;

// 为标签设置字体,默认字体

@property (strong, nonatomic) IBOutlet UILabel *normalLabel;

// 为标签设置字体,粗体字体

@property (strong, nonatomic) IBOutlet UILabel *boldLabel;

// 为标签设置字体,斜体字体

@property (strong, nonatomic) IBOutlet UILabel *italicLabel;

// 为标签设置字体,自定义字体

@property (strong, nonatomic) IBOutlet UILabel *customLabel;

@end
  1. 在viewDidLoad方法中创建字体,并为标签设置字体。
- (void)viewDidLoad

{

    [super viewDidLoad];

    // 创建字体

    UIFont *f1 = [UIFont fontWithName:@"OriyaSangamMN-Bold" size:20];

    self.customLabel.font = f1;

    // 使用系统字体

    UIFont *font1 = [UIFont systemFontOfSize:20];

    self.normalLabel.font = font1;

    // 使用系统加粗字体

    UIFont *font2 = [UIFont boldSystemFontOfSize:20];

    self.boldLabel.font = font2;

    // 使用系统字体加斜字体

    UIFont *font3 = [UIFont italicSystemFontOfSize:20];

    self.italicLabel.font = font3;

}
  1. 在display方法中获得字体家族数组和字体数组。
- (IBAction)display:(id)sender {

    // 遍历系统字体家族

    NSArray *family = [UIFont familyNames];

    for(NSString *familyName in family){

        NSLog(@"FamilyName=%@",familyName);

        NSArray *fontNames = [UIFont fontNamesForFamilyName:familyName];

        for(NSString *fontName in fontNames){

            NSLog(@"\tFontName=%@",fontName);

        }

    }

}
  1. 在get方法中获得字体属性。
- (IBAction)get:(id)sender {

    // 获得字体属性

    UIFont *f1 = [UIFont fontWithName:@"GillSans-Light" size:20];

    NSString *familyName1 = f1.familyName;

    NSString *fontName1 = f1.fontName;

    NSLog(@"FamilyName=%@",familyName1);

    NSLog(@"FontName=%@",fontName1);

}
  1. 项目运行结果如下所示。

图20.1 测试字体

可以用一个UIColor对象来定义文字的色彩。UIColor这个类提供了许多不同的方法,可以很轻松地调出任何颜色。你可以用静态方法来创建 颜色,这样它们会在停止使用后被释放。可以用灰度值、色相或者RGB复合值等多种形式来创建颜色。要创建一个简单的RGB色彩,可以指定一组4个浮点值, 分别对应红、绿、蓝和alpha值(透明度),取值均在0.0~1.0之间。

UIColor类还支持许多静态方法,可以创建系统颜色,这些颜色都经过iPhone的校正,以达到尽可能准确的地步。这些方法如下所示。

+ (UIColor *)blackColor;        // 0.0 白色

+ (UIColor *)darkGrayColor;     // 0.333 白色

+ (UIColor *)lightGrayColor;     // 0.667 白色

+ (UIColor *)whiteColor;        // 1.0 白色

+ (UIColor *)grayColor;         // 0.5 白色

+ (UIColor *)redColor;          // 1.0, 0.0, 0.0 RGB

+ (UIColor *)greenColor;        // 0.0, 1.0, 0.0 RGB

+ (UIColor *)blueColor;         // 0.0, 0.0, 1.0 RGB

+ (UIColor *)cyanColor;         // 0.0, 1.0, 1.0 RGB

+ (UIColor *)yellowColor;       // 1.0, 1.0, 0.0 RGB

+ (UIColor *)magentaColor;      // 1.0, 0.0, 1.0 RGB

+ (UIColor *)orangeColor;       // 1.0, 0.5, 0.0 RGB

+ (UIColor *)purpleColor;       // 0.5, 0.0, 0.5 RGB

+ (UIColor *)brownColor;       // 0.6, 0.4, 0.2 RGB

+ (UIColor *)clearColor;        // 0.0 白色, 0.0 alpha

另外,可以使用RGB三原色和透明度来定义颜色,+ colorWithRed:green:blue:alpha:。如果你有一张背景图片想转换为UIColor可以使用+ colorWithPatternImage:方法。如果我们有一个16进制的颜色值,想转换为UIColor,要先将16进制转换为10进制,然后使用该值除以255.0得到RGB值。例如,#F6F6F6 为一个 16 进制表示的RPG颜色,所以,需要先转换成 10进制,其中 F6 - 240,F6 - 240 ,F6 - 240

之后,使用 UIColor *testColor1= [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1];代码获得UIColor对象。下面通过一个案例来演示UIColor的用法。该案例使用一张图片为当前视图指定背景图片,并为两个标签指定颜色。实现步骤如下所示。

  1. 创建一个项目,在界面上添加两个标签,在.h头文件中添加两个标签的属性。
@interface AmakerViewController : UIViewController

// 标签1

@property (strong, nonatomic) IBOutlet UILabel *label1;

// 标签2

@property (strong, nonatomic) IBOutlet UILabel *label2;

@end
  1. 在viewDidLoad方法中为视图指定背景色,并为两个标签指定文字颜色。
- (void)viewDidLoad

{

    [super viewDidLoad];

 // 使用图片背景

    UIColor *bgColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"test.jpeg"]];

    // 为当前视图指定背景

    self.view.backgroundColor = bgColor;

    // 使用RGB创建颜色

    UIColor *labelColor1 = [UIColor colorWithRed:0.2 green:0.3 blue:0.2 alpha:1];

    // 为标签指定颜色

    self.label1.textColor = labelColor1;

    // 使用红色

    UIColor *labelColor2 = [UIColor redColor];

    // 为标签指定颜色

    self.label2.textColor = labelColor2;

}
  1. 运行程序结果如下所示。

图20.2 测试颜色

20.2 绘制文本

可以使用NSString的- (CGSize)drawAtPoint:(CGPoint)point withFont:(UIFont )font方法使用某种字体在某个点绘制文本,也可以使用- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont )font方法使用某种字体在某个矩形框中绘制文本。下面通过一个案例来演示如何绘制文本。该案例自定义了一个视图,在该视图的drawRect方法中绘制文本。实现步骤如下:

  1. 创建一个项目。

  2. 自定义一个View继承UIView,并在drawRect方法中绘制文本。

- (void)drawRect:(CGRect)rect

{

    // 要绘制的文字

    NSString *str = @"《iOS 应用开发详解》";

    // 绘制在点(20,20)使用字体大小24

    [str drawAtPoint:CGPointMake(20, 20) withFont:[UIFont systemFontOfSize:24]];

    // 在矩形中绘制

    [str drawInRect:CGRectMake(20, 50, 300, 200) withFont:[UIFont systemFontOfSize:26]];

}
  1. 将xib文件中的view类指定为自定义的view。

图20.3 绘制文本

  1. 程序运行结果如下所示。

图20.4 绘制文本

20.3 绘制图片

绘制图片和绘制文本类似,可以在某个点绘制,也可以在某个矩形中绘制。使用的方法是- (void)drawAtPoint:(CGPoint)point和- (void)drawInRect:(CGRect)rect方法。下面通过一个案例演示如何绘制图片。实现步骤如下:

  1. 创建一个项目。

  2. 自定义一个view,继承UIView,在drawRect方法中实现绘制图片。

- (void)drawRect:(CGRect)rect

{

    // 实例化一个UIImage对象

    UIImage *image = [UIImage imageNamed:@"iphone.jpg"];

    // 在(20,20)点绘制图片

    [image drawAtPoint:CGPointMake(20, 20)];

    // 在矩形中绘制图片

    [image drawInRect:CGRectMake(20, 200, 300, 200)];

}
  1. 程序运行结果如下所示。

图20.5 绘制图片

20.4 画线

在iOS中绘制直线, 使用到一个绘制环境对象CGContextRef,该对象可以使用UIGraphicsGetCurrentContext()函数获得。绘制直线和矩形等形状会使用一组以CGContextXXX打头的函数来完成,例如,CGContextSetLineWidth()设置线宽、CGContextSetStrokeColorWithColor()设置颜色、CGContextMoveToPoint()移动到某个点等。下面通过一个案例来演示如何实现划线,该案例可以实现在手指划过的起始点和结束点之间画一条直线。实现步骤如下:

  1. 创建一个项目。

  2. 自定义一个视图类view,该类继承UIView,在头文件中定义两个点。

#import <UIKit/UIKit.h>

@interface MyView : UIView

// 起始点

@property(nonatomic)CGPoint startPoint;

// 结束点

@property(nonatomic)CGPoint endPoint;

@end
  1. 在view的drawRect方法中,获得绘制上下文、设置线宽、绘制颜色、定位起始点和结束点并进行绘制。
- (void)drawRect:(CGRect)rect

{

    // 获得上下文

    CGContextRef context =UIGraphicsGetCurrentContext();

    // 设置线宽

    CGContextSetLineWidth(context, 2);

    // 设置绘制颜色

    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);

    // 移动到指定的点

    CGContextMoveToPoint(context, self.startPoint.x,  self.startPoint.y);

    // 添加一条线到指定点

    CGContextAddLineToPoint(context,  self.endPoint.x,  self.endPoint.y);

    // 绘制

    CGContextStrokePath(context);

}
  1. 覆盖touchesBegan、touchesMoved和touchesEnded方法。获得起始点和结束点。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    // 获得当前点

    UITouch *touch = [touches anyObject];

    // 初始化起始点和结束点

    self.startPoint = [touch locationInView:self];

    self.endPoint = [touch locationInView:self];

    // 触发绘制

    [self setNeedsDisplay];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    // 获得当前点

    UITouch *touch = [touches anyObject];

    // 获得结束点

    self.endPoint = [touch locationInView:self];

     // 触发绘制

    [self setNeedsDisplay];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

     // 获得当前点

    UITouch *touch = [touches anyObject];

    // 获得结束点

    self.endPoint = [touch locationInView:self];

    // 触发绘制

    [self setNeedsDisplay];

}
  1. 程序运行结果如下所示。

图20.6 画线

20.5 绘制矩形

绘制矩形和绘制直线类似,使用UIGraphicsGetCurrentContext()函数获得绘制上下文、设置绘制颜色、创建矩形、添加矩形CGContextAddRect(context, r)并且绘制矩形CGContextDrawPath(context, kCGPathFill)。

下面的案例可以手动的在界面上动态绘制矩形,实现步骤如下。

  1. 创建一个项目。

  2. 自定义一个视图类view,该类继承UIView,在头文件中定义两个点。

#import <UIKit/UIKit.h>

@interface MyView : UIView

// 起始点

@property(nonatomic)CGPoint startPoint;

// 结束点

@property(nonatomic)CGPoint endPoint;

@end
  1. 在view的drawRect方法中,获得绘制上下文、设置线宽、绘制颜色、定位起始点和结束点并进行绘制。
- (void)drawRect:(CGRect)rect

{

    // 获得上下文

    CGContextRef context = UIGraphicsGetCurrentContext();

    // 设置绘制颜色

    CGContextSetFillColorWithColor(context,  [UIColor redColor].CGColor);

    // 创建矩形

    CGRect r = CGRectMake(self.startPoint.x>self.endPoint.x?self.endPoint.x:self.startPoint.x, self.startPoint.y>self.endPoint.y?self.endPoint.y:self.startPoint.y, fabsf(self.startPoint.x-self.endPoint.x), fabsf(self.startPoint.y-self.endPoint.y));

    // 添加矩形

    CGContextAddRect(context, r);

    // 绘制矩形

    CGContextDrawPath(context, kCGPathFill);

}
  1. 覆盖touchesBegan、touchesMoved和touchesEnded方法。获得起始点和结束点。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    // 获得当前点

    UITouch *touch = [touches anyObject];

    // 初始化起始点和结束点

    self.startPoint = [touch locationInView:self];

    self.endPoint = [touch locationInView:self];

    // 触发绘制

    [self setNeedsDisplay];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    // 获得当前点

    UITouch *touch = [touches anyObject];

    // 获得结束点

    self.endPoint = [touch locationInView:self];

     // 触发绘制

    [self setNeedsDisplay];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

     // 获得当前点

    UITouch *touch = [touches anyObject];

    // 获得结束点

    self.endPoint = [touch locationInView:self];

    // 触发绘制

    [self setNeedsDisplay];

}
  1. 程序运行结果如下所示。

图20.7 画矩形

20.6 移动动画

UIView中定义了一组静态方法,来实现视图的动画效果,例如,beginAnimations开始动画、setAnimationDuration设置动画持续时间、commitAnimations提交动画等。

下面通过一个按钮来实现移动动画,移动动画除了使用上述方法外,要改变视图的重要属性是frame属性,即更改视图的位置信息。该案例在界面上添加一个图片视图和一个按钮,当点击按钮是是图片从左上角移动到右下角。实现步骤如下:

  1. 创建一个项目,在界面上添加一个图片和一个按钮,并添加图片的属性和按钮的点击事件方法。
#import <UIKit/UIKit.h>

@interface AmakerViewController : UIViewController

// 图片属性

@property (strong, nonatomic) IBOutlet UIImageView *myImage;

// 移动事件方法

- (IBAction)move:(id)sender;

@end
  1. 在move事件方法中实现动画效果。
- (IBAction)move:(id)sender {

    // 开始动画

    [UIView beginAnimations:@"myAnimation" context:(\_\_bridge void *)self.myImage];

    // 设置动画持续时间

    [UIView setAnimationDuration:5.0f];

    // 重新设置图片frame属性

    [self.myImage setFrame:CGRectMake(200.0f, 350.0f,100.0f,100.0f)];

    // 提交动画

    [UIView commitAnimations];

}
  1. 程序运行效果如下所示。

图20.8 移动动画

20.7 缩放动画

除了移动动画之外,我们还可以实现视图的缩放和旋转。本节我们来看如何实现视图的缩放,视图的缩放使用到另外一个类CGAffineTransform,即射频转换类,使用该类可以实现视图的缩放和旋转。

下面通过一个案例来演示如何实现视图的缩放。步骤如下:

  1. 创建一个项目在界面上添加一个按钮和一个图片视图。声明图片属性和按钮单击事件方法和缩放比例属性。
#import <UIKit/UIKit.h>

@interface AmakerViewController : UIViewController

// 图片属性

@property (strong, nonatomic) IBOutlet UIImageView *myImage;

// 缩放方法

- (IBAction)scale:(id)sender;

//缩放比例大小

@property(nonatomic)float scale;

@end
  1. 在scale方法中实现缩放,这里使用CGAffineTransform CGAffineTransformMakeScale (CGFloat sx,CGFloat sy);方法指定x、y轴的缩放比例。
- (IBAction)scale:(id)sender {

    // 更改缩放比例

    self.scale = self.scale==2.0?0.5:2.0;

    // 开始动画

    [UIView beginAnimations:nil context:nil];

    // 设置持续时间

    [UIView setAnimationDuration:3];

    // 设置动画效果(渐进渐出)

    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

    // 设置缩放比例

    CGAffineTransform scaleTrans =

    CGAffineTransformMakeScale(self.scale, self.scale);

    // 为图片设置转换

    self.myImage.transform = scaleTrans;

    // 提交动画

    [UIView commitAnimations];

}
  1. 程序运行结果如下所示。

图20.9  缩放动画

20.8 旋转动画

除了移动动画、缩放动画之外,我们还可以实现视图的旋转。本节我们来看如何实现视图的旋转,视图的旋转使用到另外一个类CGAffineTransform,即射频转换类,使用该类可以实现视图的缩放和旋转。

下面通过一个案例来演示如何实现视图的旋转。步骤如下:

  1. 创建一个项目在界面上添加一个按钮和一个图片视图。声明图片属性和按钮单击事件方法。
#import <UIKit/UIKit.h>

@interface AmakerViewController : UIViewController

// 图片属性

@property (strong, nonatomic) IBOutlet UIImageView *myImage;

// 缩放方法

- (IBAction) rotate:(id)sender;

@end
  1. 在rotate方法中实现旋转,这里使用CGAffineTransformMakeRotation(180 * M_PI / 180);方法设置旋转弧度。
- (IBAction) rotate:(id)sender {

 // 开始动画

    [UIView beginAnimations:nil context:nil];

    // 设置持续时间

    [UIView setAnimationDuration:3];

    // 设置动画效果(渐进渐出)

    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

    // 设置旋转弧度

    CGAffineTransform rotationTrans =

    CGAffineTransformMakeRotation(180 * M\_PI / 180);

    // 为图片设置转换

    self.myImage.transform = rotationTrans;    // 提交动画

    [UIView commitAnimations];

}
  1. 程序运行结果如下所示。

图20.10  旋转动画