動畫只是Core Animation特性的冰山一角
Core Animation功能
Core Animation自身并不是一個繪圖系統(tǒng)储笑。它只是一個負責在硬件上合成和操縱應用內(nèi)容的基礎構(gòu)件悯恍。
視圖層級?圖層樹?呈現(xiàn)樹?渲染樹 組成
視圖:
UIVIew類都是從UIView基類(父類)派生出來的跨扮,UIview用來處理觸摸事件何荚,做一些簡單的動畫效果(累死滑動 漸變)
每一個UIView都有一個CAlayer實例圖層屬性!8透选!
CALayer類 管理子圖層的位置规求,不關心任何響應事件,不處理用戶的交互卵惦,他有一些方法和屬性來做動畫效果? ? ? ? 注:CALayer處理響應事件有 -containsPoint:和-hitTest:幫你處理 阻肿。 ???下面會講到
UIView沒有暴露出來的CALayer的功能:
陰影,圓角沮尿,帶顏色的邊框 3D變換 非矩形范圍 透明遮罩 多級非線性動畫
CALayer之 contents屬性:ID屬性(給CGImage類型丛塌,但真正賦值的內(nèi)容是CGimageRef)
//CGimageRef 是指向CGImage結(jié)構(gòu)的指針
layer.contents = (__bridge id)image.CGImage;
這樣我們就可以不需要額外的圖層 直接在ayerView的宿主圖層contents屬性設置圖片了!
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:@"xxx"];
self.view.layer.contents = (__bridge id)image.CGImage;
//圖片變形處理上
//self.view.contentMode = UIViewContentModeScaleAspectFit;
//? ? contentMode操作對應的是應用層
//? ? CALayer 對應的是 contentsGravity
self.view.layer.contentsGravity = kCAGravityResizeAspect;
}
/*
NSString * const kCAGravityCenter
NSString * const kCAGravityTop
NSString * const kCAGravityBottom
NSString * const kCAGravityLeft
NSString * const kCAGravityRight
NSString * const kCAGravityTopLeft
NSString * const kCAGravityTopRight
NSString * const kCAGravityBottomLeft
NSString * const kCAGravityBottomRight
NSString * const kCAGravityResize
NSString * const kCAGravityResizeAspect
NSString * const kCAGravityResizeAspectFill
*/
使用contentsGravity替換contentMode
//? ? self.view.contentMode = UIViewContentModeScaleAspectFit;
//NSString類型
self.view.layer.contentsGravity = kCAGravityResizeAspect;
layout 還有:
contentScale (定義尺寸 視圖大小比例 ) 這里我就不多說了
masksToBounds(顯示是否超出邊界的內(nèi)容) 這里我就不多說了
contentsRect(默認是{0畜疾,0赴邻,1,1}) ?<大概說說>
拼接圖片:
UIImage *img = [UIImage imageNamed:@"yyy.png"];
[self addSpriteImage:img withContentRect:CGRectMake(0, 0, 0.5, 0.5)];
[self addSpriteImage:img withContentRect:CGRectMake(0.5, 0, 0.5, 0)];
[self addSpriteImage:img withContentRect:CGRectMake(0, 0.5, 0, 0.5)];
[self addSpriteImage:img withContentRect:CGRectMake(0.5, 0.5, 0, 0)];
}
-(void)addSpriteImage:(UIImage*)img withContentRect:(CGRect)rect{
self.view.layer.contents = (__bridge id)img .CGImage;
self.view.layer.contentsGravity = kCAGravityResizeAspect;
self.view.layer.contentsRect = rect;
}
contentsCenter ?CGRect ?定義一個固定的邊框和在圖層上可拉伸的區(qū)域) 例如:我們的聊天框(邊框不變 拉伸中間1個像素可以根據(jù)文字改變聊天框的大蟹却贰)這些切割都會用到。這里我就不多說了
下面我們聊聊繪制圖
繼承UIView 實現(xiàn)-drawRect:方法
:
1、如果UIView檢測到這個方法 方法會被調(diào)用(利用Core Graphics繪制) 會分配一個寄宿圖 像素尺寸=視圖大小*contentsScale(默認1.0浮點數(shù) ??講過)
如果不需要就不要創(chuàng)建 這會造成CUP資源和內(nèi)存浪費:所以蘋果建議如果沒有自定義的代碼任務不要在子類中寫一個這個方法
2嫂拴、然后內(nèi)容被緩存起來 直到更新調(diào)用:-setNeedDisplay方法
需要重繪時 CALayer 調(diào)用 (void)displayLayer:(CALayer*)layer;來請求它的代理
如果代理不實現(xiàn)displayLayer:方法 CALayer會嘗試調(diào)用-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx;
繪制圖時你也不必要實現(xiàn)-displayLayer:和-drawLayer:inContext: 通常做法是實現(xiàn)UIView的drawRect:方法 UIView會幫你做完剩余的工作 包括需要重繪的時候調(diào)用-display方法辩恼。
下面我們再聊聊 --圖層幾何學
UIView有三種比較重要的布局:frame bounds center
? ? ? ? ? ? ? ? ? ? CALayer對應的叫:frame bounds position
frame:當旋轉(zhuǎn) 變換后可能和bounds的寬高不一致:
frame實際上是代表覆蓋在圖層旋轉(zhuǎn)之后的整個軸對齊的矩形區(qū)域 如圖所示:
錨點 anchorPoint(默認{0.5聘萨,0.5})
視圖的center 和圖層的position屬性都是指定了anchorPoint的對與父圖層位置
圖層的anchorPoint通過position控制frame的位置 anchorPoint屬性并沒有被UIView接口暴露出來,這也是視圖的position屬性叫做“center”的原因。
CALayer坐標系 里的z軸
CALayer存在于三維空間中 zPosition和 anchorPointZ,都是Z軸上描述圖層位置的浮點類型
-(void)viewDidLoad{
[super viewDidLoad];
//redView在前 greenView在后 我們可以使用下面的方法將greenView前置
self.greenView.layer.zPosition = 1.0f;
}
HitTesting
CALayer處理響應事件 -containsPoint:和-hitTest:
使用containsPoint判斷被點擊的圖層 (接收CGPoint類型參數(shù) )
使用hitTest判斷被點擊的圖層(接收CGPoint類型參數(shù) 返回圖層本身)測算順序依賴圖層樹順序(UIView處理事件類似)
? ? ? ? ? ? ? ? ? ? ? ? ? {
如果改變了圖層Z軸的順序傲隶,就不能檢查到最前方的視圖點擊事件F故 G狻砸讳!
雖然在屏幕上順序是在前面 但是不能改變傳遞的順序;兑尽!酗钞!
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
自動布局
UIViewAutoresizingMask和
NSLayoutConstraint ? API
但如果想隨意控制CALayer的布局葫录,就需要手動操作 使用:CALayerDelegate的
-(void)layoutSublayersOfLayer:(CALayer*)layer;
執(zhí)行這個方法的條件:
1少孝、bounds發(fā)生改變
2钱磅、-setNeedLayout方法被調(diào)用
這里插入一個知識點:
-setNeedsLayout方法: 標記為需要重新布局,異步調(diào)用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定會被調(diào)用
-layoutIfNeeded方法:如果狠持,有需要刷新的標記得院,立即調(diào)用layoutSubviews進行布局(如果沒有標記里覆,不會調(diào)用layoutSubviews)
而layoutSubviews 被觸發(fā)是:
1??渡冻、init初始化不會觸發(fā)layoutSubviews
但是是用initWithFrame 進行初始化時巍举,當rect的值不為CGRectZero時,也會觸發(fā)
2??、addSubview會觸發(fā)layoutSubviews
3??寂祥、設置view的Frame會觸發(fā)layoutSubviews涛菠,當然前提是frame的值設置前后發(fā)生了變化
4??莉御、滾動一個UIScrollView會觸發(fā)layoutSubviews
5??、旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件
6??俗冻、改變一個UIView大小的時候也會觸發(fā)父UIView上的layoutSubviews事件
總結(jié):這就是為什么我們不單獨使用圖層 而是使用視圖來構(gòu)建應用程序的原因之一了
視覺效果:
圓角 conrnerRadius 設置圓角曲率 (浮點型)
只影響背景顏色 不影響背景圖片和子圖層
設置masksToBounds = yes 可以將圖層里面的東西截取掉
圖層邊框 borderWidth(浮點型) 和 borderColor(默認是黑色 ? CGColorRef類型)
陰影 ?shadowOpacity(默認值0 ?;>0時可以顯示在任意圖層之下礁叔;類型:0-1的浮點數(shù))
shadowColor(CGColorRef類型)
shadowOffset(小編做了demo 陰影是CGSize類型,坐標圓點是從本體的左上角開始的) ??
?注:默認值是:(0迄薄,-3)向上投影
shadowRadius 控制陰影的模糊(半徑)面積大小
shadowPath 屬性提高代碼繪制陰影的性能 代碼如下:
- (void)viewDidLoad {
[superviewDidLoad];
CALayer*layer = [[CALayeralloc]init];
layer.frame=CGRectMake(100,100,100,100);
layer.backgroundColor= [UIColorredColor].CGColor;
[self.view.layeraddSublayer:layer];
layer.shadowOpacity=1.0;
layer.shadowColor= [UIColorblackColor].CGColor;
layer.shadowOffset=CGSizeMake(5,5);
layer.shadowRadius=10;
CGMutablePathRefmuPath =CGPathCreateMutable();
// add ?矩形和圓形有單獨的方法 其它的使用UIBezierPath類繪制
CGPathAddRect(muPath,NULL,CGRectMake(0,0,100,200));
layer.shadowPath= muPath;
// release
CGPathRelease(muPath);
}
圖層蒙版 mask
- (void)viewDidLoad {
[superviewDidLoad];
UIImage*img = [UIImageimageNamed:@"222.png"];
UIImageView* imgView = [[UIImageViewalloc]initWithFrame:CGRectMake(20,100,300,300)];
imgView.image= img;
[self.view addSubview:imgView];
CALayer* layer = [CALayer layer];
layer.frame=CGRectMake(50,50,100,100);//坐標是從imgView的左上角開始的
// 上面已經(jīng)講解了加載img的方式圖片加到蒙版上
layer.contents= (__bridgeid)img.CGImage;
//設置imgViewlayer為自定義的layer
imgView.layer.mask=layer;
}
效果圖:
拉伸過濾
屬性
minificationFilter(縮欣殴亍)
magnificationFilter(放大)
三種過濾器
線性過濾保留了形狀,最近過濾保留了像素的差異
kCAFilterLinear 線性濾波(雙線性濾波)
kCAFilterNearest ?取樣最近的單像素點
kCAFilterTrilinear 三線性濾波
組透明 opacity
shouldRasterize :YES ?(圖層及子圖層都會被整合成衣蛾整體的圖片)
當然還得需要設置:rasterizationScale = [UIScreen mainScreen].scale;
(防止出現(xiàn)Retina屏幕像素化)
變換
仿射變換
CGPoint
CGAffineTransform
Transformed CGPoint
使用CGpoint的每一列和CGAffineTransform矩陣的每一行對應的元素相乘再求和讥蔽,就形成了新的CGPoint類型的結(jié)果死姚。
如果覺得矩陣不好理解 蘋果還提供了三個API
先縮小50% 再旋轉(zhuǎn)30度 最后右移動200像素
CGAffineTransformtramsform =CGAffineTransformIdentity;//初始化一個空的 沒有任何變化的tramsform
tramsform =CGAffineTransformScale(tramsform,0.5,0.5);//縮小50%
tramsform =CGAffineTransformRotate(tramsform,M_PI/180.0*30);//旋轉(zhuǎn)30度
tramsform =CGAffineTransformTranslate(tramsform,200,0);//右移
myView.layer.affineTransform = tramsform;
3D變換
CGPoint ? zPosition CaTransfrom3D ?Transformed Point
比較2D ?平移和旋轉(zhuǎn)多出了 Z軸
X Y Z 軸的方向:
移動:
x 向右 正數(shù)?
y 向下 正數(shù)
z 向屏幕前 正數(shù)
旋轉(zhuǎn):
x 上邊界向屏幕里面倒 正數(shù)
y 右邊界向屏幕里面倒 正數(shù)
z 順時針旋轉(zhuǎn) 正數(shù)
透視效果:M34
m34 用來計算到底離視角多遠(默認是0)
-1.0/d ?
1、負數(shù)表示上邊界透視
2勤篮、/d ?d 表示想象中視角相機和屏幕之間的距離(像素) 距離越大偏的越邪磷怼(實際生活中想象一下)
self.view.backgroundColor= [UIColorblackColor];
UIImageView* imgView = [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"222"]];
imgView.frame=CGRectMake(100,44,200,200);
imgView.backgroundColor= [UIColorwhiteColor];
[self.viewaddSubview:imgView];
CATransform3Dtrans3d =CATransform3DIdentity;
trans3d.m34=1.0/150;
trans3d =CATransform3DRotate(trans3d,M_PI_4,1,0,0);
imgView.layer.transform= trans3d;
滅點?
這個點被 Core Animation定義在 錨點anchorPoint 位置上 默認{0.5芙盘,0.5}上面講到過
一個視圖還好說 ? 但是多個視圖怎么辦??对妄???
sublayerTransForm 使用
概論的我就不多說了,舉個例子
我們先創(chuàng)建一個容器backGroundView.layer ?
使用sublayerTransForm 于是所以的子圖層都會自動繼承這個變換方法腌且。這樣滅點就在容器的中點了 再使用CATransform3DMake...設置各個子圖層變換
背面
CALayer 的doubleSided可以設置圖層的背面是否被繪制 YES/NO
默認是可以繪制的
扁平化圖層?
每個視圖都存在不同的3D空間里 每個圖層的3D場景都是扁平化的 這個3D 效果僅僅是繪制在圖層的表面。所以場景里面的東西不會隨著觀察的角度的改變而發(fā)生改變榛瓮,圖層也是同樣的道理
固態(tài)對象
我們來用六個獨立的視圖來構(gòu)成立方體的各個面
先上圖 再發(fā)代碼
打散點 再看一下 實現(xiàn)方法:
int off=CGRectGetWidth(v.frame)/2+50;
代碼如下
#import"ViewController.h"
@interfaceViewController()
@property(weak,nonatomic)IBOutletUIView*containerView;
@property(strong,nonatomic)IBOutletCollection(UIView)NSArray* views;
@end
@implementationViewController
- (void)viewDidLoad {
[superviewDidLoad];
CATransform3Dperspective =CATransform3DIdentity;
perspective.m34= -1.0/500.0;
perspective =CATransform3DRotate(perspective, -M_PI_4,1,0,0);
perspective =CATransform3DRotate(perspective,M_PI_4,0,1,0);
self.containerView.layer.sublayerTransform= perspective;
UIView*v =self.views[0];
//這里設置視圖邊長的一半
intoff=CGRectGetWidth(v.frame)/2;
[selfcreate3DViews:off];
}
-(void)create3DViews:(NSInteger)off{
//正邊"1"的界面
CATransform3Dtransform =CATransform3DMakeTranslation(0,0, off );
[selfaddView:0withTransform:transform];
//右邊"2"的界面
transform =CATransform3DMakeTranslation(off,0,0);
transform =CATransform3DRotate(transform,M_PI_2,0,1,0);
[selfaddView:1withTransform:transform];
//上面"3"的界面
transform =CATransform3DMakeTranslation(0, -off,0);
transform =CATransform3DRotate(transform,M_PI_2,1,0,0);
[selfaddView:2withTransform:transform];
//下面"4"的界面
transform =CATransform3DMakeTranslation(0, off,0);
transform =CATransform3DRotate(transform, -M_PI_2,1,0,0);
[selfaddView:3withTransform:transform];
//左邊"5"界面
transform =CATransform3DMakeTranslation(-off,0,0);
transform =CATransform3DRotate(transform, -M_PI_2,0,1,0);
[selfaddView:4withTransform:transform];
//正面背面"6"的界面
transform =CATransform3DMakeTranslation(0,0, -off);
transform =CATransform3DRotate(transform,M_PI,0,1,0);
[selfaddView:5withTransform:transform];
}
-(void)addView:(NSInteger)index withTransform:(CATransform3D)transform{
UIView* view =self.views[index];
[self.containerViewaddSubview:view];
index+=index;
view.backgroundColor= [UIColorcolorWithRed:index*40/255.fgreen:1blue:1alpha:1];
CGSizecontainerSize =self.containerView.bounds.size;
view.center=CGPointMake(containerSize.width/2.0, containerSize.height/2.0);
view.layer.transform= transform;//分別變換
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
xib截圖如下
光亮和陰影
正太向量:垂直于表面的向量(書上概論的我就不說了铺董,其實我自己也不知道,而且也沒必要知道這玩意)
我們需要用到GLKit框架
沒一個CATransform3D都被轉(zhuǎn)換成GLMatrix4,然后通過GLMatrix4GLMatrix3 函數(shù)得到一個3x3的旋轉(zhuǎn)矩陣(指定了圖層的方向)可以使用它得到正太向量的值禀晓。
在上面代碼的-(void)addView:(NSInteger)index withTransform:(CATransform3D)transform 方法里面調(diào)用
[self applyLightToViews:view.layer];方法
-(void)applyLightToViews:(CALayer*)view{
floatAMBIENT_LIGHT =50;
floatLIGHT_DIFAULT =50;
CALayer*layer = [CALayerlayer];
layer.frame= view.bounds;
[viewaddSublayer:layer];
CATransform3Dtransform = view.transform;
GLKMatrix4matrix4 = *(GLKMatrix4*)&transform;
GLKMatrix3matrix3 =GLKMatrix4GetMatrix3(matrix4);
GLKVector3normal =GLKVector3Make(0,0,1);
normal =GLKMatrix3MultiplyVector3(matrix3, normal);
normal =GLKVector3Normalize(normal);
GLKVector3light =GLKVector3Normalize(GLKVector3Make(LIGHT_DIFAULT,0,0));
floatdotProduct =GLKVector3DotProduct(light, normal);
CGFloat shadow =1+dotProduct-AMBIENT_LIGHT;
layer.backgroundColor = [UIColor ?colorWithWhite:0alpha:shadow].CGColor;
}
大概意思就是再加一層layer ?我覺得也不是很實用 ?精续,代碼已經(jīng)貼出來了 ,有這方面需求的可以繼續(xù)擴展粹懒,這里就不詳細說明了重付。
點擊事件
由于添加View的順序不一樣 3界面的被4 5 6 界面遮擋 ?導致無法響應點擊事件。
可以設置userInteractionEnabled屬性為NO ?保留3 界面YES?
或者把視圖3 覆蓋到6上(其他幾個界面不沖突)
繪制圖層 CAShapeLayer
CAShapeLayer和Core Graphics相比 優(yōu)勢 (了解一下就好)
渲染快速?
高速使用內(nèi)存(不需要CALayer一樣 需要寄宿圖層)
不會被圖層邊界剪切
不會出現(xiàn)像素化
創(chuàng)建一個CGPath
可以使用paintcode工具進行繪制 然后創(chuàng)建CAShapLayer 調(diào)用shaplayer.path 賦值path 最后加載layer
CATextLayer
富文本
有興趣的老鐵可以研究一下Core Text 都是iOS3.2之后的功能
.h頁面
#import@class UIColor;
typedef enum
{
left,
center,
right,
}ZFTextAlignment;
typedef void(^LabelTextBlock)(NSRange range,UIColor *fuColor);
typedef void(^LabelTextBlockMore)(NSRange range);
@interface ZF_CATextLabel : CATextLayer
//基礎樣式
-(instancetype)createCATextLayerWithFrame:(CGRect)frame fontSize:(CGFloat)fontSize textColor:(UIColor*)color textAlignment:(ZFTextAlignment)alignment textString:(NSString*)str;
//特殊樣式(富文本)// 這里沒必要使用copy
@property (nonatomic, strong) LabelTextBlock labelBlock;
@property (nonatomic, strong) LabelTextBlockMore labelMoreBlock;
@end
.m頁面
#import "ZF_CATextLabel.h"#import#import@implementation ZF_CATextLabel
-(instancetype)createCATextLayerWithFrame:(CGRect)frame fontSize:(CGFloat)fontSize textColor:(UIColor*)color textAlignment:(ZFTextAlignment)alignment textString:(NSString*)str{
if ([super init]) {
self.frame = frame;
self.foregroundColor = color.CGColor;
self.alignmentMode = [self ZFTextAlignment:alignment];
self.wrapped = YES;
UIFont * font = [UIFont systemFontOfSize:fontSize];
CFStringRef fontName = (__bridge CFStringRef)font.fontName;
CGFontRef fontRef = CGFontCreateWithFontName(fontName);
self.font = fontRef;
self.fontSize = font.pointSize;
CGFontRelease(fontRef);
self.string = str;
//設置retina顯示
self.contentsScale = [UIScreen mainScreen].scale;
//////////////////////////////////////////////////////////////////////
__weak typeof(self) weakSelf = self;
self.labelBlock = ^(NSRange range, UIColor *fuColor) {
NSMutableAttributedString *string = nil;
string = [[NSMutableAttributedString alloc] initWithString:str];
//convert UIFont to a CTFont
CFStringRef fontName2 = (__bridge CFStringRef)font.fontName;
CGFloat fontSize2 = font.pointSize;
CTFontRef fontRef2 = CTFontCreateWithName(fontName2, fontSize2, NULL);
//set text attributes
NSDictionary *attribs = @{
(__bridge id)kCTForegroundColorAttributeName:(__bridge id)color.CGColor,
(__bridge id)kCTFontAttributeName: (__bridge id)fontRef2
};
[string setAttributes:attribs range:NSMakeRange(0, [string length])];
attribs = @{
(__bridge id)kCTForegroundColorAttributeName: (__bridge id)fuColor.CGColor,
(__bridge id)kCTUnderlineStyleAttributeName: @(kCTUnderlineStyleSingle),
(__bridge id)kCTFontAttributeName: (__bridge id)fontRef2
};
[string setAttributes:attribs range:range];
weakSelf.labelMoreBlock = ^(NSRange range) {
[string setAttributes:attribs range:range];
weakSelf.string = string;
};
//release the CTFont we created earlier
CFRelease(fontRef);
//set layer text
weakSelf.string = string;
};
}
return self;
}
//設置對齊方式
-(NSString*)ZFTextAlignment:(ZFTextAlignment)alignment{
NSString * left = kCAAlignmentLeft;
NSString * center = kCAAlignmentCenter;
NSString * right = kCAAlignmentRight;
switch (alignment) {
case 0:
return left;
break;
case 1:
return center;
break;
case 2:
return right;
break;
default:
break;
}
}
controller 調(diào)用
ZF_CATextLabel * label = [[ZF_CATextLabel alloc]init];
[label createCATextLayerWithFrame:CGRectMake(100, 100, 200, 200) fontSize:20 textColor:[UIColor blackColor] textAlignment:center textString:@"wwwwewhrwiuejrojeigrfhqergqierhgerbgqrjefnerfejk"];
label.labelBlock(NSMakeRange(5, 6), [UIColor yellowColor]);
label.labelMoreBlock(NSMakeRange(13, 4));
[self.view.layer addSublayer:label];
效果圖:
CATransformLayer
構(gòu)造復雜的3D事物(用于構(gòu)造一個層級的3D結(jié)構(gòu))
CAGradientLayer ?漸變
用來生成兩種或多種顏色平滑漸變
雙色效果
多色效果+locations
代碼:
CAReplicatorLayer(生成相似圖層)
擴展用于投影 ? ?反射:
CAScrollLayer
CALayer *layer = [CALayer layer];
UIImage *image = [UIImage imageNamed:@"xxx"];
layer.contents = (__bridge id)image.CGImage;
[self.view.layer addSublayer:layer];
scrollLayer = [CAScrollLayer layer];
scrollLayer.backgroundColor = [UIColor blackColor].CGColor;
scrollLayer.frame = CGRectMake(60, 60, 200, 200);
layer.frame = scrollLayer.frame;
[scrollLayer addSublayer:layer];
[self.view.layer addSublayer:scrollLayer];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(changes:)];
[self.view addGestureRecognizer:pan];
}
-(void)changes:(UIPanGestureRecognizer*)pan{
CGPoint translation = [pan translationInView:self.view];
CGPoint origin = scrollLayer.bounds.origin;
origin = CGPointMake(origin.x-translation.x, origin.y-translation.y);
[scrollLayer scrollToPoint:origin];
[pan setTranslation:CGPointZero inView:self.view];
}
效果圖
CATiledLayer加載大圖(大圖分解成小片)
http://blog.sina.com.cn/s/blog_7192ec8e0100qz8m.html
Retina小圖
layer.contentsScale = [UIScreen mainScreen].scale;
意味著圖將會以一半的大小渲染在Retina設備上
CAEmitterLayer(粒子引擎)
Emitter:發(fā)射器
CAEAGLLayer(處理高性能圖形繪制)
引入(GLKit)(OpenGLES)框架
AVPlayerLayer(iOS上播放視頻)
需要添加AVFoundation框架
動畫
隱式動畫 (沒有指定動畫的類型)
事務(包含一系列屬性動畫集合的機制确垫,當事務提交時,開始用一個動畫過渡到新值)
[CATransaction begin];
/**
*? 中間設置CATransaction的變化
**/
[CATransaction commit];
顯示動畫
屬性動畫
使用kvc對動畫打標簽
@property (nonatomic, weak) IBOutlet UIImageView *hourHand;
@property (nonatomic, weak) IBOutlet UIImageView *minuteHand;
@property (nonatomic, weak) IBOutlet UIImageView *secondHand;
@property (nonatomic, weak) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
self.minuteHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
//start timer
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(tick) userInfo:nil repeats:YES];
[self updateHandsAnimated:NO];
}
- (void)tick
{
[self updateHandsAnimated:YES];
}
- (void)updateHandsAnimated:(BOOL)animated
{
//convert time to hours, minutes and seconds
#if __IPHONE_OS_VERSION_MAX_ALLOWED <= 80000 // 當前Xcode支持iOS8及以下 測試時可以不寫
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
CGFloat hourAngle = (components.hour / 12.0) * M_PI * 2.0;
//calculate hour hand angle //calculate minute hand angle
CGFloat minuteAngle = (components.minute / 60.0) * M_PI * 2.0;
//calculate second hand angle
CGFloat secondAngle = (components.second / 60.0) * M_PI * 2.0;
//rotate hands
[self setAngle:hourAngle forHand:self.hourHand animated:animated];
[self setAngle:minuteAngle forHand:self.minuteHand animated:animated];
[self setAngle:secondAngle forHand:self.secondHand animated:animated];
#else
NSLog(@"%s",__func__);
#endif
}
- (void)setAngle:(CGFloat)angle forHand:(UIView *)handView animated:(BOOL)animated
{
//旋轉(zhuǎn) CATransform3DMakeRotation
CATransform3D transform = CATransform3DMakeRotation(angle, 0, 0, 1);
if (animated) {
//create transform animation
CABasicAnimation *animation = [CABasicAnimation animation];
[self updateHandsAnimated:NO];
animation.keyPath = @"transform";
animation.toValue = [NSValue valueWithCATransform3D:transform];
animation.duration = 0.5;
animation.delegate = self;
[animation setValue:handView forKey:@"handView"];
[handView.layer addAnimation:animation forKey:nil];
} else {
//set transform directly
handView.layer.transform = transform;
}
}
//一共兩個代理方法 一個是開始 一個是停止
- (void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag
{
//set final position for hand view
UIView *handView = [anim valueForKey:@"handView"];
handView.layer.transform = [anim.toValue CATransform3DValue];
}
關鍵幀動畫
CAKeyframeAnimation(CAPropertyAnimation的子類)
通過幀 改變背景色
- (void)viewDidLoad {
[super viewDidLoad];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
//? ? ? ? bounds = 大小?
//? ? ? ? contentsRect = 內(nèi)容矩形
//? ? ? ? frame = 位置
//? ? ? ? hidden = 隱藏
//? ? ? ? mask = 標記
//? ? ? ? maskToBounds
//? ? ? ? position = 位置
//? ? ? ? shadowOffset = 陰影偏移?
//? ? ? ? shadowColor = 陰影顏色
//? ? ? ? shadowRadius = 陰影角度
//? ? ? ? transform.scale = 比例轉(zhuǎn)換
//? ? ? ? transform.scale.x = 寬的比例轉(zhuǎn)換
//? ? ? ? transform.scale.y = 高的比例轉(zhuǎn)換
//? ? ? ? transform.rotation.z = 平面圖的旋轉(zhuǎn)
//? ? ? ? opacity = 透明度
//? ? ? ? margin=邊框間隔?
//? ? ? ? zPosition = 平面圖的位置
//? ? ? ? backgroundColor = 背景色
//? ? ? ? cornerRadius = layer的角度
//? ? ? ? borderWidth = 邊框?qū)挾?/p>
//? ? ? ? contents = 內(nèi)容?
animation.keyPath =@"backgroundColor";
animation.duration = 2.0f;
animation.values = @[(__bridge id)[UIColor redColor].CGColor,(__bridge id)[UIColor greenColor].CGColor,(__bridge id)[UIColor yellowColor].CGColor,(__bridge id)[UIColor blueColor].CGColor];
[self.view.layer addAnimation:animation forKey:nil];
}
沿著一個貝塞爾曲線對圖層做動畫
動畫組
CABasicAnimation和 CAKeyframeAnimation僅僅作用于單獨的屬性
CAAnimationGroup 可以把這些動畫組合起來
效果圖
過渡
使用type(NSString)和subtype來標識變換的效果
type ? NSString{
KCATransitionFade (默認) ?淡入淡出效果
KCATransitionMoveIn 頂部滑動進入
KCATransitionPush ?把舊圖層從另一側(cè)推出去的效果
KCATransitionReveal 把原始的圖層滑動出去顯示新的外觀
}
subtype{
KCATransitionFromRight
KCATransitionFromLeft
KCATransitionFromTop
KCATransitionFromBottom
}
隱式過渡
自定義動畫(UIView)
[UIView ?transitionWithView:noteViewduration:0.6 options:UIViewAnimationOptionTransitionCurlUp animations:^{
// 在noteView視圖上設置過渡效果
NSString *currentText =noteView.text;
noteView.text =nextText;
self.nextText =currentText;
}completion:^(BOOL finished){
}];
- (void)fadeMe {
[UIView animateWithDuration:1.0 animations:^{
fadeMeView.alpha = 0.0f;? ? // 作用在fadeMeView視圖
}];
- (void)moveMe {
[UIView animateWithDuration:0.5 animations:^{
moveMeView.center = CGPointMake(moveMeView.center.x
, moveMeView.center.y - 200); // 作用在moveMeView視圖
}];
}
renderInContext創(chuàng)建自定義過渡效果
在動畫過程中取消動畫
補充:之前-addAnimation:forkey:方法中的key參數(shù)來添加動畫之后檢索一個動畫 使用如下方法:
-(CAAnimation*)animationForKey:(NSString*)key帽芽;
但是不支持動畫過程中修改動畫 删掀,我們使用:
移除對應的:
-(void)removeAnimationForKey:(NSString*)key;
移除所以的:
-(void)removeAllAnimations;
CAMediaTiming協(xié)議
定義了一段動畫內(nèi)控制逝去時間的屬性的集合
CALayer 和CAAnimation都實現(xiàn)了這個協(xié)議
duration ? (CFTimeInterval類型 导街、雙進度浮點型) ? ? ? 持續(xù)時間
repeatCount ? 重復 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 默認都是0:0.25秒和1次
- (void)viewDidLoad {
[super viewDidLoad];
[self animationDoor];
}
-(void)animationDoor{
CALayer * doorLayer = [CALayer layer];
doorLayer.frame = CGRectMake(100, 100, 100, 180);
[self.view.layer addSublayer:doorLayer];
doorLayer.backgroundColor = [UIColor greenColor].CGColor;
doorLayer.position = CGPointMake(200, 200);
doorLayer.anchorPoint = CGPointMake(0, 0.5);
CATransform3D trans3d = CATransform3DIdentity;
trans3d.m34 = 1.0/500.;
self.view.layer.sublayerTransform = trans3d;
CABasicAnimation * basicAnimation = [CABasicAnimation animation];
basicAnimation.keyPath = @"transform.rotation.y";
basicAnimation.toValue = @(M_PI);//旋轉(zhuǎn)到多少度
basicAnimation.duration = 3.;
basicAnimation.repeatDuration = HUGE_VALF;//float
basicAnimation.autoreverses = YES;
[doorLayer addAnimation:basicAnimation forKey:nil];
}
相對時間(加速 延遲 偏移)
beginTime 動畫開始前的延遲時間 默認是0(表示立即執(zhí)行)
speed 是時間的倍數(shù)默認是1.0
timeOffset 讓動畫快進到某一點(當timeOffset= 1/2 ?時爬迟,表示從一般的地方開始執(zhí)行)
fileModel
更新中。菊匿。。
更多可參考https://www.gitbook.com/book/zsisme/ios-/details
- 文/潘曉璐 我一進店門陶冷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钙姊,“玉大人,你說我怎么就攤上這事埂伦∩范睿” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長膊毁。 經(jīng)常有香客問我胀莹,道長,這世上最難降的妖魔是什么婚温? 我笑而不...
- 正文 為了忘掉前任描焰,我火速辦了婚禮,結(jié)果婚禮上栅螟,老公的妹妹穿的比我還像新娘荆秦。我一直安慰自己,他們只是感情好嵌巷,可當我...
- 文/花漫 我一把揭開白布萄凤。 她就那樣靜靜地躺著,像睡著了一般搪哪。 火紅的嫁衣襯著肌膚如雪靡努。 梳的紋絲不亂的頭發(fā)上,一...
- 文/蒼蘭香墨 我猛地睜開眼梁肿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了觅彰?” 一聲冷哼從身側(cè)響起吩蔑,我...
- 正文 年R本政府宣布,位于F島的核電站个榕,受9級特大地震影響篡石,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜西采,卻給世界環(huán)境...
- 文/蒙蒙 一凰萨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧械馆,春花似錦胖眷、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至尾菇,卻和暖如春境析,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背派诬。 一陣腳步聲響...
推薦閱讀更多精彩內(nèi)容
- 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜奈辰,今天將帶大家一窺ios動畫全貌栏妖。在這里你可以看...
- >復雜的組織都是專門化的 >Catharine R. Stimpson 到目前為止,我們已經(jīng)探討過`CALayer...
- 本文轉(zhuǎn)載自:http://www.cocoachina.com/ios/20150104/10814.html ...
- 如果想讓事情變得順利冯挎,只有靠自己--夏爾·紀堯姆 上一章介紹了隱式動畫的概念。隱式動畫是在iOS平臺創(chuàng)建動態(tài)用戶界...