H:/0805/01_CADisplayLink_ViewController.m
// ViewController.m
// CADisplayLink动画时间处理
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 使用CALayer,需要引入<QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
// 间隔时间:方式2:用全局静态变量,记录程序运行开始,屏幕刷新的总次数
static long steps;
@interface ViewController ()
{
// 游戏时钟
CADisplayLink *_gameTimer;
// 间隔时间:方式1:用时钟触发的初始时间
CFTimeInterval _startTime;
}
@end
@implementation ViewController
/**
需求:能够自己指定间隔多长时间,去触发要执行的任务!
间隔时间:方式1:用成员变量
1. 需要一个成员变量,记录时钟起始的“时间点”
2. 计算成员变量与时钟触发时的时间差值,如果大于我们指定的时间,
再去执行我们需要执行的任务。
*/
#pragma mark - 使用指定时间处理CADisplayLink触发时间的方法(1)
- (void)updateTimer:(CADisplayLink *)sender
{
// 如果_startTime=0,说明是第一次触发时钟,需要记录时钟的时钟戳记
if (_startTime == 0) {
_startTime = sender.timestamp;
}
// 时钟触发的时间差值
CFTimeInterval deltaTime = sender.timestamp - _startTime;
if (deltaTime > 1.0) {
NSLog(@"大约1秒,时钟触发了 %f", sender.timestamp);
// 更新_startTime的数值,记录本次执行任务的时间
_startTime = sender.timestamp;
}
}
#pragma mark - 使用指定时间处理CADisplayLink触发时间的方法(2)
/**
使用一个“全局”的长整形记录屏幕刷新的次数,然后,用模的方式判断时间
在Box2D的物理引擎中,时钟触发的方法也叫做step。
step方法的调用频率是:1/60s
*/
- (void)step
{
// 假定每隔一秒触发一次方法,只需模以60即可
if (steps % 60 == 1) {
NSLog(@"时钟触发了! %ld", steps);
}
steps++;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 首先将启动的时间点设置为0
_startTime = 0.0f;
// 将屏幕刷新总次数设置为0
steps = 0;
// 时钟设置1:初始化游戏时钟
_gameTimer = [CADisplayLink displayLinkWithTarget:self
selector:@selector(step)];
// 时钟设置2:把游戏时钟,添加到主运行循环
[_gameTimer addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSDefaultRunLoopMode];
}
@end
H:/0805/02_帧动画_CADisplayLink时钟动画_ViewController.h
//
// ViewController.h
// 基本动画02-序列帧动画
//
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
// 赵云
@property (weak, nonatomic) IBOutlet UIImageView *zhaoyunImage;
// 燕子
@property (weak, nonatomic) IBOutlet UIImageView *birdImage;
@end
H:/0805/02_帧动画_CADisplayLink时钟动画_ViewController.m
// ViewController.m
// 基本动画02-序列帧动画
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 使用CALayer,需要引入<QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
//时间间隔方式2:使用全局静态变量:在时钟方法中累加,每1/60s
static long steps;
@interface ViewController ()
{
// 游戏时钟
CADisplayLink *_gameTimer;
// 雪花图像
UIImage *_snowImage;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 自定义方法中实现,赵云的帧动画
[self createZhaoyunImage];
// 自定义方法中实现,燕子的帧动画
[self createBirdImage];
// 自定义方法中实现,雪花飞舞的时钟动画
[self snowFly];
}
// 创建赵云的序列帧动画
- (void)createZhaoyunImage
{
// 设置ImageView的序列帧动画
// 1. 需要一个数组
NSMutableArray *images = [NSMutableArray array];
for (int i = 1; i < 11; i++) {
NSString *fileName = [NSString stringWithFormat:@"/images/zy/%d.png", i];
// imageNamed方法用之后,会缓存在内存中
UIImage *image = [UIImage imageNamed:fileName];
[images addObject:image];
}
[_zhaoyunImage setImage:images[0]];
// 设置动画图像数组
[_zhaoyunImage setAnimationImages:images];
// 设置10张图片播放的时长
[_zhaoyunImage setAnimationDuration:1.0f];
// 开始动画
[_zhaoyunImage startAnimating];
}
// 当点击屏幕时,赵云就停止 或者 开始动画
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([_zhaoyunImage isAnimating]) {
// 序列帧动画每次停止的时候,都会显示设置的图像,而不是当前播放到的图像
[_zhaoyunImage stopAnimating];
} else {
[_zhaoyunImage startAnimating];
}
}
// 设置燕子的序列帧动画,并设置燕子的拖拽手势监听
- (void)createBirdImage
{
// 设置燕子的序列帧动画
NSArray *images = @[[UIImage imageNamed:@"/images/素材/燕子1.png"],
[UIImage imageNamed:@"/images/素材/燕子2.png"]];
[_birdImage setAnimationImages:images];
[_birdImage setAnimationDuration:1.2f];
[_birdImage startAnimating];
// 定义手势,关联监听手势的对象和方法
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:@selector(dragBird:)];
// 为Image添加手势识别器为pan手势
[_birdImage addGestureRecognizer:pan];
// 并且,记得设置燕子图片允许交互
[_birdImage setUserInteractionEnabled:YES];
}
#pragma mark - 监听拖拽燕子,更改燕子的帧动画频率
- (void)dragBird:(UIPanGestureRecognizer *)sender
{
// 先需要知道手指的位置
CGPoint location = [sender locationInView:self.view];
// 手势状态改是UIGestureRecognizerStateChanged的时候,手指还没有离开屏幕
// 这个时候,修改鸟的位置,同时让鸟扑腾
if (sender.state == UIGestureRecognizerStateChanged) {
// 注意:如果要修改播放中的序列帧动画
// 1. 需要先停止动画
[_birdImage stopAnimating];
// 2. 修改动画频率变快,形成挣扎的效果
[_birdImage setAnimationDuration:0.2f];
// 3. 重新启动动画
[_birdImage startAnimating];
// 设置燕子的位置
[_birdImage setCenter:location];
} else if (sender.state == UIGestureRecognizerStateEnded) {
// 恢复燕子慢悠悠飞行的姿态
// 1. 也是要先停止动画
[_birdImage stopAnimating];
// 2. 然后再修改动画频率
[_birdImage setAnimationDuration:1.2f];
// 3. 最后重新启动动画即可
[_birdImage startAnimating];
}
}
#pragma mark - 雪花飞舞的时钟动画
- (void)snowFly
{
// 全局静态变量,用于记录时钟的时间间隔
steps = 0;
// 初始化雪花图像,只需要加载一次即可
_snowImage = [UIImage imageNamed:@"/images/素材/雪花"];
// 时钟步骤1:初始化,并指定每1/60秒要调用的时钟方法
_gameTimer = [CADisplayLink displayLinkWithTarget:self
selector:@selector(step)];
// 时钟步骤2:加入主运行循环
[_gameTimer addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSDefaultRunLoopMode];
}
#pragma mark - 时钟处理方法
- (void)step
{
// 假设每秒钟绘制6个雪花,即1/6秒绘制一个雪花
if (steps % 10 == 0) {
// 绘制雪花
UIImageView *imageView = [[UIImageView alloc]
initWithImage:_snowImage];
// 指定雪花出现的位置
CGPoint startPoint = CGPointMake(arc4random() % 320, -30.0);
// 指定雪花结束的位置
CGPoint endPoint = CGPointMake(arc4random() % 320, 490);
/**
考虑问题
1. 雪花太亮,需要改一下目的地透明度
2. 如果雪花会转就更好,需要改变目的地的角度*/
// 雪花尺寸
CGFloat len = arc4random() % 5 + 10;
[imageView setFrame:CGRectMake(0, 0, len, len)];
// 设置起始点
[imageView setCenter:startPoint];
// 把雪花图像添加到视图
[self.view addSubview:imageView];
[UIView animateWithDuration:6.0f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
// 设置目的地
[imageView setCenter:endPoint];
// 设置最终透明度
[imageView setAlpha:0.2f];
// 设置雪花最终旋转角度
[imageView setTransform:CGAffineTransformMakeRotation(M_PI)];
} completion:^(BOOL finished) {
// 千万不要忘了,完成动画之后,要从父视图删除
[imageView removeFromSuperview];
}];
}
// 绘制星星,原理同雪花,此处省略
if (steps % 20 == 0) {
// 绘制星星代码
// [self drawStar];
}
// 全局静态变量steps累加的频率是1/60秒
steps++;
}
@end
H:/0805/03_SVProgressHUD_NSTimer_UIActivityIndicatorView_ViewController.h
//
// ViewController.h
// 基本动画01-Indicator视图演练
//
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
// 演练UIActivityIndicatorView,正在加载指示器
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicatorView;
@end
H:/0805/03_SVProgressHUD_NSTimer_UIActivityIndicatorView_ViewController.m
// ViewController.m
// 基本动画01-Indicator视图演练
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 导入第3方库文件,正在加载指示器...
#import "SVProgressHUD.h"
@interface ViewController ()
@end
@implementation ViewController
/**
IndicatorView的使用
触摸屏幕,显示
再触摸屏幕,关闭*/
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 出现问题了,因为使用了SVProgress的maskType属性,当前视图无法接受触摸事件
// 需要想办法关闭
// 解决方法1
// sleep
// 解决方法2
// 使用NSTimer
if ([_indicatorView isAnimating]) {
[SVProgressHUD dismiss];
[_indicatorView stopAnimating];
} else {
[SVProgressHUD showWithStatus:@"正在加载...指示器~~~"
maskType:SVProgressHUDMaskTypeGradient];
// 调动指示器,转圈圈,正在加载...
[_indicatorView startAnimating];
// 指示器一启动,就无法交互了,所以要把时钟放在这里
// NSTimer的调度方法
// 1. 指定时间间隔,即定时多少秒
// 2. 时间到了,将要触发时的哪个对象的哪个方法
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:@selector(updateTimer:) userInfo:nil repeats:NO];
}
}
// NSTimer调用方法的参数,只能是NSTimer,
// 使用参数好处:不需要使用成员变量,就可以将时钟关闭
- (void)updateTimer:(NSTimer *)timer
{
[SVProgressHUD dismiss];
[_indicatorView stopAnimating];
// 关闭时钟
[timer invalidate];
}
@end
H:/0805/04_CALayer基本使用_ViewController.h
//
// ViewController.h
// CALayer01-CALayer基本使用
//
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
// 演练视图
@property (weak, nonatomic) IBOutlet UIView *myView;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
H:/0805/04_CALayer基本使用_ViewController.m
// ViewController.m
// CALayer01-CALayer基本使用
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 使用CALayer,需要引入<QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self imageViewLayerDemo];
}
// 设置UIView的CALayer的演示
- (void)myViewLayerDemo
{
// 1. 圆角
[_myView.layer setCornerRadius:100];
// 2. 阴影
[_myView.layer setShadowOffset:CGSizeMake(-10, -10)];
// 在使用CALayer的时候,不能直接用以UI开头的对象,需进行转换为CG对象,譬如UIColor
[_myView.layer setShadowColor:[UIColor darkGrayColor].CGColor];
[_myView.layer setShadowOpacity:0.5];// 不透明度
// 3. 边框 宽度和颜色
[_myView.layer setBorderWidth:3];
[_myView.layer setBorderColor:[UIColor whiteColor].CGColor];
}
// 设置UIImage的CALayer的演示
- (void)imageViewLayerDemo
{
// 1. 圆角,在UIImageView里面,不止一个图层
[_imageView.layer setCornerRadius:100];
// 使用maskstoBounds属性,可以让所有子图层都跟随主图层
[_imageView.layer setMasksToBounds:YES];
// 2. 阴影,在UIImageView中,有些Layer的属性是冲突的
[_imageView.layer setShadowOffset:CGSizeMake(10, 10)];
[_imageView.layer setShadowColor:[UIColor redColor].CGColor];
[_imageView.layer setShadowOpacity:0.5];
// 3. 边框setMasksToBounds=YES,边框是有效的
[_imageView.layer setBorderWidth:5];
[_imageView.layer setBorderColor:[UIColor whiteColor].CGColor];
// 4. 翻转,三维变形一次只能做一个
// [_imageView.layer setTransform:CATransform3DMakeRotation(M_PI, 1, 0, 0)];
// // 5. 比例缩放
// [_imageView.layer setTransform:CATransform3DMakeScale(0.5, 2.0, 1)];
// // 6. 平移
// [_imageView.layer setTransform:CATransform3DMakeTranslation(0, -100, 0)];
[_imageView.layer setValue:@M_PI_2 forKeyPath:@"transform.rotation.z"];
}
@end
H:/0805/05_自定义图层_ViewController.m
// ViewController.m
// CALayer02-自定义图层
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 使用CALayer,需要引入<QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
{
CALayer *layer;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 1. 新建图层
layer = [CALayer layer];
// 2. 设置图层属性
// bounds:宽度和高度
[layer setBounds:CGRectMake(0, 0, 200, 200)];
// backgroundColor: 背景颜色(CGColorRef类型)UI对象要转成CG对象
[layer setBackgroundColor:[UIColor greenColor].CGColor];
// contents:内容CGImageRef,设置内容的时候,需要用id做一次强转
UIImage *image = [UIImage imageNamed:@"头像1"];
// UI对象要转成CG对象
[layer setContents:(id)[image CGImage]];
// position:位置(默认指中点)
[layer setPosition:CGPointMake(200, 200)];
// anchorPoint:锚点(x,y的范围都是0-1,默认数值是0.5,0.5)
// 锚点又称为定位点,是用来定位position的所在位置的那个像素
/**
Position属性用于指定屏幕上的坐标位置,是一个像素点
锚点用于指定相对于图片的坐标位置,用锚点去对应找Postion所在像素
*/
[layer setAnchorPoint:CGPointMake(1, 1)];
// 以锚点为中心,进行旋转的
[layer setTransform:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)];
// 3. 把图层添加到当前视图
[self.view.layer addSublayer:layer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 通过设置锚点,来实现隐藏效果
if (layer.anchorPoint.x == 0) {
[layer setAnchorPoint:CGPointMake(1, 1)];
} else {
[layer setAnchorPoint:CGPointMake(0, 0)];
}
}
@end
H:/0805/06_CALayer隐式动画_ViewController.m
// ViewController.m
// CALayer03.隐式动画
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 使用CALayer,需要引入<QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
{
CALayer *layer;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 新建一个CALayer图层
layer = [CALayer layer];
[layer setPosition:CGPointMake(100, 100)];
[layer setBounds:CGRectMake(0, 0, 200, 200)];
[layer setBackgroundColor:[UIColor redColor].CGColor];
UIImage *image = [UIImage imageNamed:@"头像1"];
// 所在UI对象要转成CG对象
[layer setContents:(id)[image CGImage]];
// 使用maskstoBounds属性,可以让所有子图层都跟随主图层???
[layer setMasksToBounds:YES];
[self.view.layer addSublayer:layer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 触摸屏幕时,把UIView的中心点位置,调整到手指触摸位置
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
// 1. 透明度
[layer setOpacity:0.5f];
// 2. 边框大小
[layer setBounds:CGRectMake(0, 0, 100, 100)];
// 3. 位置
[layer setPosition:location];
// 4. 设置一个圆角
[layer setCornerRadius:100];
// 5. 设置边框
[layer setBorderColor:[UIColor blueColor].CGColor];
[layer setBorderWidth:10];
}
@end
H:/0805/07_自定义绘制CALayer图层_ViewController.m
// ViewController.m
// CALayer04.自定义绘制图层
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
// 使用CALayer,需要引入<QuartzCore/QuartzCore.h>
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
{
CALayer *_layer;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 1. 新建图层
_layer = [CALayer layer];
[_layer setBounds:CGRectMake(0, 0, 200, 200)];
[_layer setPosition:CGPointMake(100, 100)];
[_layer setBackgroundColor:[UIColor redColor].CGColor];
// 不能将UIView设置为这个CALayer的delegate,
// 因为UIView对象已经是内部层的delegate,再次设置会出问题
// [_layer setDelegate:self.view];
// 设置代理为当前控制器
[_layer setDelegate:self];
// setNeedsDisplay内部会自动调用:drawLayer:inContext:
[_layer setNeedsDisplay];
[self.view.layer addSublayer:_layer];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
// 在CALayer里面不能使用UI对象,需要使用CG对象
// 在CALayer里面不能使用UIColor的方式设置颜色
// [[UIColor redColor]set];
CGContextSetRGBFillColor(ctx, 1, 1, 0, 1);
CGContextFillEllipseInRect(ctx, CGRectMake(0, 0, 200, 200));
}
@end
H:/0805/08_Quartz2D_圆弧_MyDrawingView.h
//
// MyDrawingView.h
// Quartz2D-绘制圆弧演练
//
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface MyDrawingView : UIView
// 圆弧的百分比数值,数值范围从0~1
@property (assign, nonatomic) CGFloat percent;
@end
H:/0805/08_Quartz2D_圆弧_MyDrawingView.m
// MyDrawingView.m
// Quartz2D-绘制圆弧演练
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "MyDrawingView.h"
@implementation MyDrawingView
#pragma mark - 百分比Setter方法
- (void)setPercent:(CGFloat)percent
{
_percent = percent;
// setNeedsDisplay方法内部会自动调用drawRect方法,且drawRect不能手动调用
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
if (_percent > 0) {
[self drawShapeArc2:_percent outsideR:100.0 insideR:80.0
fillColor:[UIColor redColor] strokeColor:[UIColor blackColor]];
}
}
#pragma mark - 自定义方法:使用贝塞尔曲线绘制圆弧
/**
参数说明:
percent: 弧度占360度的百分比,数值从0~1
outsideR: 圆弧外圈半径
insideR: 圆弧内圈半径
fillColor: 填充颜色
strokeColor: 边线颜色
*/
- (void)drawShapeArc2:(CGFloat)percent
outsideR:(CGFloat)outSideR
insideR:(CGFloat)insideR
fillColor:(UIColor *)fillColor
strokeColor:(UIColor *)strokeColor
{
// 起始角度为-90,在圆周的上方
CGFloat startAngle = -M_PI_2;
// 计算技术角度,用传入参数的百分比 * 360 - 90
CGFloat endAngle = -M_PI_2 + percent * 2 * M_PI;
// 绘制第一条路径(弧线),从起始角度,绘制到目标角度
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(160, 230)
radius:outSideR
startAngle:startAngle
endAngle:endAngle
clockwise:1];
// 添加一条反方向的弧线,注意需要从目标角度绘制到起始角度
[path addArcWithCenter:CGPointMake(160, 230)
radius:insideR
startAngle:endAngle
endAngle:startAngle
clockwise:0];
// 关闭路径
[path closePath];
// 设置填充颜色
[fillColor setFill];
// 设置边线颜色
[strokeColor setStroke];
// 路径填充
[path fill];
// 路径绘线
[path stroke];
}
@end
H:/0805/08_Quartz2D_圆弧_ViewController.m
// ViewController.m
// Quartz2D-绘制圆弧演练
// Created by apple on 13-8-5.
// Copyright (c) 2013年 itcast. All rights reserved.
/**
功能描述
1. 触摸屏幕时,启动时钟
2. 时钟每秒钟触发50次
3. 每次时钟触发时,百分比进度+1
4. 百分比进度更新时,视图更新圆弧的显示
5. 百分比=100时关闭时钟
*/
#import "ViewController.h"
#import "MyDrawingView.h"
@interface ViewController ()
{
// 当前百分比数值
NSInteger _percentValue;
// 是否完成
BOOL _isDone;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_isDone = YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (_isDone) {
_isDone = NO;
[NSTimer scheduledTimerWithTimeInterval:0.02
target:self
selector:@selector(updateTimer:)
userInfo:nil repeats:YES];
}
}
- (void)updateTimer:(NSTimer *)timer
{
MyDrawingView *view = (MyDrawingView *)self.view;
// 更新视图的百分比属性
[view setPercent:++_percentValue / 100.0];
if (_percentValue == 100) {
// 关闭时钟
[timer invalidate];
_isDone = YES;
NSLog(@"OK");
}
}
@end