某種意義 上蘋果已經(jīng)提供了優(yōu)美簡潔的UIView接口,對簡單需求沒必要處理CALayer,因為蘋果已經(jīng)通過UIView 的高級API 間接地使得動畫變得很簡單。
但簡單就不可避免地帶來靈活上的缺陷,UIView 沒有暴露CALayer的功能:
- 陰影,圓角,帶顏色的邊框
- 3D 變換
- 非矩形范圍
- 透明遮罩
- 多級非線性動畫
基礎(chǔ)屬性
UIImage *image = [UIImage imageNamed:@"1.jpg"];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(0, 0, 300, 400);
[self.view.layer addSublayer:layer];
self.myLayer = layer;
//1.contents 屬性(id 類型)
//image.CGImage 返回一個CGImageRef 指向CGImage結(jié)構(gòu)的指針
//CGImageRef 不是Cocoa對象,而是一個Core Foundation 類型,需要 __bridge轉(zhuǎn)換
layer.contents = (__bridge id)image.CGImage;
//2. imageView圖片有contentMode 屬性設(shè)置圖片填充方式
layer.contentsGravity = ;//不被拉伸
//3. maskToBounds 相當于 clipsToBounds 屬性來設(shè)置邊界
//默認情況下,UIView 和 CALayer 都會繪制走出邊界的內(nèi)容或子視圖
//4. contentsRect 允許我們在圖層邊框里顯示寄宿圖的一個子域
//它使用單位坐標(0-1),是一個相對值,是相對于寄宿圖的尺寸而言
//這個屬性可以將加載的一張圖片,切成多張圖片
layer.contentsRect = CGRectMake(0.4, 0.2, 0.3, 0.3);
//5. UIView 有三個布局屬性 frame,bounds,center
//CALayer 有三個布局屬性 frame,bounds,position
//frame 是外部坐標,bounds 是內(nèi)部坐標
//當操縱視圖的 frame,實際上是在改變位于視圖下方 CALayer 的 frame
//當視圖旋轉(zhuǎn)后,其frame 與 bounds 一般會不一致。因為frame 代表了覆蓋在
//圖層旋轉(zhuǎn)后整個軸對齊的矩形區(qū)域。
//6. 錨點
//anchorPoint默認居中(0.5,0.5),可以理解為移動圖層的把柄
//可以通過移動錨點來改變 frame,錨點改變后,其旋轉(zhuǎn)中心點也改變
//7. conrnerRadius屬性控制圖層的曲率,只影響背景顏色而不影響子視圖
//maskToBounds 設(shè)成 YES,才會有截取
//borderColor 設(shè)置邊框顏色
//borderWidth 設(shè)置邊框粗細
//8. shadowColor 陰影顏色
//shadowOffset 陰影方向及距離
//shadowRadius 陰影模糊度
//shadowPath 陰影路徑
//注意:開啟了masksToBounds 屬性,越界全被截剪,陰影則無法顯示
//9. mask 屬性本身也是一個CALayer類型
//opacity 與 alpha 相似,都會影響子圖層。
//10. 當有多個子視圖時,由于透明度疊加造成效果很不理想。
//shouldRasterize 屬性會將多個圖層整合成整體圖片然后設(shè)置透明度
//self.myLayer.shouldRasterize = YES;
//11. 變換
//UIView transform 屬性,CGAffineTransform 類型(二維坐標系)
//CALayer transform 屬性,CATransform3D 類型 (三維坐標第)
// affineTransform 屬性,CGAffineTransform類型
//layer.affineTransform = CGAffineTransformMakeRotation(M_PI/4);
//混合變換
/*
CGAffineTransform transform = CGAffineTransformIdentity;//初始空值
transform = CGAffineTransformScale(transform, 0.5, 0.5);
transform = CGAffineTransformRotate(transform, M_PI/4);
transform = CGAffineTransformTranslate(transform, 10, 30);
layer.affineTransform = transform;
*/
//或者
//CGAffineTransformConcat(transform, transform);
//旋轉(zhuǎn)
//基于最初的位置旋轉(zhuǎn)
//self.myLayer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
//基于給定的transform 旋轉(zhuǎn)
//self.myLayer.transform = CATransform3DRotate(self.myLayer.transform, M_PI, 0, 1, 0);
//**********透視效果,默認通過 m34 來改變*************
//CATransform3D transform = CATransform3DIdentity;
//transform.m34 = -1.0/500; //(500-1000是一個比較和適的值)
//transform = CATransform3DRotate(transform, M_PI_4, 1, 0, 0);
//layer.transform = transform;
//12. 背面,當視圖旋轉(zhuǎn)后背面不會被繪制
//self.myLayer.doubleSided = NO;
CATransition (過渡動畫)
- CATransition動畫可以實現(xiàn)別樣的輪播圖動效
- (void)transitionAnimation{
CATransition *transition = [CATransition animation];
transition.fillMode = kCAFillModeForwards;
transition.removedOnCompletion = YES;
transition.startProgress = 0.0;
transition.endProgress = 1.0;
transition.duration = 1.0;
transition.type = kCATransitionMoveIn;
/*
私有接口(慎用)
cube 立體翻轉(zhuǎn)
oglFlip 翻轉(zhuǎn)
suckEffect 收縮效果
rippleEffect 水滴波紋
pageCurl 翻頁
pageUnCurl
cameralIrisHollowOpen 攝像頭打開效果
cameraIrisHollowClose 關(guān)閉效果
*/
/*
公有接口
kCATransitionFade 淡出效果
kCATransitionMoveIn 新視圖移到舊視圖上
kCATransitionPush 新視圖推出舊視圖
kCATransitionReveal 移開舊視圖顯示新視圖
*/
transition.subtype = kCATransitionFromLeft;
/*
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom
*/
[self.imageView.layer addAnimation:transition forKey:@"transition"];
[self setNewImage];
}
只要用手勢或計時器回調(diào)下面方法即可實現(xiàn)輪播效果
- (void)setNewImage{
static int i = 5;
i++;
int imageIndex = i%5;
NSString *imageName = [NSString stringWithFormat:@"%d.jpg",imageIndex];
[self.imageView setImage:[UIImage imageNamed:imageName]];
}
或者
[UIView transitionWithView:_imageView
duration:1.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
// [self.imageView setFrame:CGRectMake(0, 0, 300, 300)];
[self setNewImage];
} completion:nil];
- CATransition動畫實現(xiàn)簡單的轉(zhuǎn)場效果
// 在window上執(zhí)行CATransition, 即可在ViewController轉(zhuǎn)場時執(zhí)行動畫。
[self.view.window.layer addAnimation:animation forKey:@"kTransitionAnimation"];
PresentedViewController *presentedVC = [[PresentedViewController alloc] init];
[self presentViewController:presentedVC animated:NO completion:nil];
- tabBarViewController 可以添加過渡效果
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *viewController1 = [[FirstViewController alloc]initWithNibName:@"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil];
viewController2.title = @"第一";
viewController1.title = @"第二";
self.tabBarController = [[UITabBarController alloc]init];
self.tabBarController.viewControllers = @[viewController1,viewController2];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
CATransition *transition = [CATransition animation];
transition.type = kCATransitionFade;
transition.duration= 3; //3秒時間過渡效果會明顯一些
[self.tabBarController.view.layer addAnimation:transition forKey:@"transition"];
}
CAKeyframeAnimation
- (void)keyFrameAnimation{
CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.view.center
radius:100
startAngle:0
endAngle:2 * M_PI
clockwise:YES];//順時針方向
keyframeAnimation.path = path.CGPath;//UIKit框架轉(zhuǎn)CG框架
keyframeAnimation.duration = 3;
keyframeAnimation.repeatCount = 1;
keyframeAnimation.fillMode = kCAFillModeForwards;
keyframeAnimation.removedOnCompletion = NO;
keyframeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
//這個屬性很有意思。
keyframeAnimation.rotationMode = KCAAnimationRotateAuto;
//*******設(shè)置value后會覆蓋path********//
//KeyframeAnimation.values = @[ ];
[self.layer addAnimation:keyframeAnimation forKey:@"keyframeAnimation"];
}
- (void)addShakeAnimationForView:(UIView *)view withDuration:(NSTimeInterval)duration {
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
CGFloat currentTx = view.transform.tx;
animation.delegate = self;
animation.duration = duration;
animation.values = @[ @(currentTx), @(currentTx + 10), @(currentTx-8), @(currentTx + 8), @(currentTx -5), @(currentTx + 5), @(currentTx) ];
animation.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1) ];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.layer addAnimation:animation forKey:@"keyframeAnimation"];
}
CABasicAnimation
/**
* CABsicAnimation 的實例對象只是一個數(shù)據(jù)模型,
* addAnimation:forKey只是將對象的copy,所以也可以添加到另外一個layer上
*
*/
/**
* 為什么動畫會返回原狀態(tài)
* 添加動畫時,真正移動的并不是視圖本身,而是presentation Layer的一個緩存
* 動畫開始,presentation Layer開始移動,原始layer隱藏
* 動畫結(jié)束,presentation layer開始移除,原始layer顯示
*/
- (void)basicAnimation{
//旋轉(zhuǎn)動畫
CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
rotateAnimation.duration = 3.0;
rotateAnimation.repeatCount = 100;
rotateAnimation.autoreverses = YES;
rotateAnimation.fromValue = [NSNumber numberWithFloat:0];
rotateAnimation.toValue = [NSNumber numberWithFloat:6*M_PI];
[self.layer addAnimation:rotateAnimation forKey:@"rotate"];
//放大 縮小
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration = 3.0;
scaleAnimation.repeatCount = 1;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];
scaleAnimation.toValue = [NSNumber numberWithFloat:3];
//動畫結(jié)束后保持移動后的位置
scaleAnimation.removedOnCompletion = NO;
scaleAnimation.fillMode = kCAFillModeForwards;
//設(shè)置動畫速率
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
/**
* kCAMediaTimingFunctionLinear
* kCAMediaTimingFunctionEaseIn 開始慢,后來快
* kCAMediaTimingFunctionEaseOut
*/
[self.layer addAnimation:scaleAnimation forKey:@"scale"];
//設(shè)置代理可以監(jiān)測動畫開始和結(jié)束時的動作
scaleAnimation.delegate = self;
//平移動畫
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 3.0;
animation.autoreverses = YES;
animation.repeatCount = 100;
animation.fromValue = [NSValue valueWithCGPoint:_layer.position];
CGPoint toPoint = _layer.position;
toPoint.x = toPoint.x+180;
animation.toValue = [NSValue valueWithCGPoint:toPoint];
[self.layer addAnimation:animation forKey:@"move"];
}
UIView動畫
- 動畫使用
3D變換可將圖層順序更改
動畫中更改使用transform可以快速方便地改變frame
[UIView animateWithDuration:0.5 animations:^{
self.testView.layer.transform = CATransform3DMakeTranslation(10, 10, 1);
} completion:nil];
[UIView animateWithDuration:0.5 animations:^{
self.testView.transform = CGAffineTransformMakeTranslation(10, 10);
} completion:nil];
或
-(void)normalAnimation{
[UIView animateWithDuration:2
delay:1
options:UIViewAnimationOptionRepeat
animations:^{
[UIView setAnimationRepeatCount:3];
[UIView setAnimationRepeatAutoreverses:YES];
self.redView.center = self.view.center;
}
completion:^(BOOL finished){
NSLog(@"finished--%d",finished); }
];
}
或
UIViewAnimationOptions op = UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionBeginFromCurrentState;
[UIView animateWithDuration:0.1
delay:0
options:op
animations:^{
//view縮小
[_view.layer setValue:@(0.5) forKeyPath:@"transform.scale"];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0 options:op animations:^{
// view放大
[_view.layer setValue:@(1.08) forKeyPath:@"transform.scale"];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0 options:op animations:^{
//view恢得原樣
[_view.layer setValue:@(1) forKeyPath:@"transform.scale"];
} completion:NULL];
}];
}];
- spring動畫
-(void)springAnimation{
[UIView animateWithDuration:1
delay:0
usingSpringWithDamping:100//類似彈簧振動效果,越小越明顯
initialSpringVelocity:10 //初始速度
options:UIViewAnimationOptionCurveLinear
animations:^{
[UIView setAnimationRepeatCount:5];
self.redView.frame = CGRectMake(50, 200, 100, 100);
}
completion:^(BOOL finished) {
}];
}
- 關(guān)鍵幀動畫
-(void)keyFrameAnimationView{
[UIView animateKeyframesWithDuration:6
delay:0.0
options:UIViewKeyframeAnimationOptionLayoutSubviews
animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.3 animations:^{
self.redView.center = self.view.center;
}];
[UIView addKeyframeWithRelativeStartTime:0.3 relativeDuration:0.3 animations:^{
self.redView.backgroundColor = [UIColor orangeColor];
}];
[UIView addKeyframeWithRelativeStartTime:0.6 relativeDuration:0.4 animations:^{
CGRect rect= self.redView.frame;
rect.size.width +=rect.size.width;
rect.size.height +=rect.size.height;
self.redView.frame =rect;
}];
//relativeStartTime
//relativeDuration 都是相對時間,占總時間的占比
} completion:^(BOOL finished) {
NSLog(@"動畫結(jié)束");
}];
}
UIView動畫停止
- (void)startAnimation {
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveLinear |
UIViewAnimationOptionAllowUserInteraction
animations:^(void) {
//動畫
} completion:^(BOOL finished) {
if(!self.canceled) {
__weak id weakSelf = self;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[weakSelf startAnimation];
}];
}
}];
}