標籤:
在iOS中都會牽扯到圖形轉換,動畫效果,添加視圖,等等的一系列問題,在設計頁面,設計圖形,添加動畫的時候都會使用到這個知識。
簡單的說他就是視圖的圖層,但又不是視圖,因為視圖可以和使用者互動,添加響應事件,添加視圖等等,但是CALayer並不可以添加響應事件等等,它只是一個視圖的圖層,就是這個圖片的顯示層,展示層,只能夠顯示內容,比如展示背景顏色,展示圖片,設定邊框,等等。
- UIView上面的rootLayer 發生改變的話 子圖層也會發生變化
- 如果想要改變 button的視圖形狀邊框等,要改變的不止有一個視圖 改變的只是其中一個視圖的rootLayer 它會顯示出顯示未被裁切的邊框
- rootLayer上面沒有動畫效果
- CALayer發生改變 子圖層不會跟隨發生改變 內建動畫效果(當改變屬性值的時候) 隱式動畫
理解了CALayer之後就可以大致的有一個瞭解,有個要使用的方向,而且單獨對圖層做設計修改的時候功能也會比以前多很多,而且當你改變他的圖層數值的時候,CALayer是內建隱式動畫效果的
接下來看一個圖來大概瞭解下視圖的圖層關係,下面是我某一個頁面的3D圖,不得不說Xcode的強大
在左邊我們可以詳細看到他們的圖層是怎麼樣嵌套的,當你選中一個圖層的時候你也可以在上面看到他的所有父視圖,或者說在他之前有幾層圖層,分別是什麼,當你對一個視圖進行處理的時候,打算處理他的哪一個圖層,都很重要。
如果你只處理了一層,比如我為了美觀,我想把collectionView上面的cell設定了這個屬性
cell.layer.cornerRadius = 10;
他就會有一點圓邊,讓使用者感覺上至少比方方正正的好看很多,但是我cell上面還有一層imageView和label,他們都在contentView上面,在這兩個屬性都為空白的時候,cell沒有問題,但一旦我設定了圖片,而且是填滿狀態的,顯示圖片是沒有問題,但是你會發現這個cell他又變成方方正正的了,這難免會讓人很煩躁,有時候確實會因為各種原因頭疼,甚至因此卡住,或者放棄這個效果,白白浪費了一段時間。
感覺有點像打廣告的。。所以你要設定的時候要清楚的知道自己要對哪一個圖層進行處理,在這裡我們只要再給他的ImageView層處理一下layer就可以了
cell.imageView.layer.cornerRadius = 10; //裁切內容的尺寸 cell.imageView.layer.masksToBounds = YES;
接下來說一層的一些屬性,可修改的一些屬性
- bounds 邊境範圍
- position 中心點
- zPosition z軸中心點
- anchorPoint 錨點 ?????
- 錨點 預設錨點是與中心店重合 錨點的最小值是0,0最大值1,1 預設值是0.5,0.5
- 當視圖 改變的時候 是以錨點為基準去改變
- 錨點的值與位置
- anchorPointZ Z軸錨點
- transform 轉換形態
- frame NO. Animatable 座標
- hidden 隱藏
- doubleSided 圖層背面是否顯示
- geometryFlipped 翻轉 顛倒
- masksToBounds 裁切邊境
- contents 內容
- opaque 不透明度
- allowsEdgeAntialiasing 是否使用 變形後的消除鋸齒
- backgroundColor 背景顏色
- borderWidth 邊框寬
- borderColor 邊框顏色
- opacity 不透明度
- shadowColor 陰影顏色
- shadowOpacity 陰影不透明度
- rasterizationScale 防止Retina螢幕像素化
- shadowOffset 陰影位移
- shadowRadius 陰影的半徑
通過設定這些屬性都可以讓視圖的形態等發生改變,要注意在給CALayer一些屬性賦值的時候,他需要的值得類型都是一些特殊類型的值
比如我們之前在給View的transform賦值的時候使用的都是CGAffineTransform類型的,而給CALayer的transform賦值的時候使用使用的是CATransform3D類型的值,包括改變背景顏色也是使用的CGColor,圖片是CGImageRef所以使用的時候要注意。
在給他們修改屬性的時候,因為CALayer內建隱式動畫,所以在觸發事件等改變他的屬性的時候都會內建動畫效果。
在下面要具體說一下CALayer裡面的錨點屬性,也是動畫,視圖效果使用最重要的一個屬性
大家如果有用過UIView的一些animation的基礎動畫的時候可能會知道,沒用過也沒關係,你肯定知道行動裝置檢視都是調整視圖的center值來做到使視圖移動到另外一個位置,設定bounds來放大或縮小一個視圖。這裡我們不重點說這個。
在這裡錨點和視圖的center值有點類似,也是通過知道他的中心點,來設定這個中心點,來改變他的位置,不過在這裡我們不用中心點了,用的就是錨點來替代了這個點,他可以讓視圖以任意點為挪動點,比如,一個長長的汽車在行駛,汽車上面的人的位置都是固定不變的,你可以通過改變汽車的中心點來讓汽車移動,也可以通過某一個人的位置的改變來改變汽車的位置,比如我現在想讓這個汽車通過一個山洞
比如星星是司機,在這裡我可以通過這個司機的位置,把司機的X增加一定的數值來讓這個車通過這個山洞,和通過改變中心點是一個道理,只不過是這個中心點變了,變成了我們定義的一個錨點。也可以理解成把牛栓在樹上,他怎麼跑也跑不出這個點,以這個點為移動點來做動作。
理解了這個點的含義,就能做很多事情,比如有些動畫就是通過固定錨點來讓視圖做一些動作
原諒我做不出動圖T T,沒有美工,在這裡我設定圖片的旋轉就是讓他轉動半個圓,但是我把它的錨點設定成了他的右下角,所以他會以右下角來轉動。
我們簡單的寫一個執行個體的layer
我們把CALayer定義成一個全域變數
{ CALayer *layer; }layer = [CALayer layer];layer.frame = CGRectMake(0, 0, 100, 100);layer.backgroundColor = [UIColor colorWithRed:1.000 green:0.607 blue:0.468 alpha:1.000].CGColor; //在這裡注意我們要添加的是一個layer所以要把它添加到我們要修改視圖的layer上面 [self.view.layer addSublayer:layer];
然後我們寫一個touchBegan的方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{UITouch *touch = [touches anyObject];CGFloat width = CGRectGetWidth(layer.bounds)!=100?100:25;layer.bounds = CGRectMake(0, 0, width, width);layer.cornerRadius = layer.cornerRadius !=50 ? 50:0;layer.position = [touch locationInView:self.view]; }
在這裡我們也簡單寫一個錨點的使用,我們繼續定義一個CALayer
@property (nonatomic,strong)CALayer *pointLayer; self.pointLayer.anchorPoint = CGPointMake(0.5 , 0.9);self.pointLayer.contents = (id)[UIImage imageNamed:@"要旋轉的圖片"].CGImage;- (CALayer *)pointLayer{if (_pointLayer) { return _pointLayer;}_pointLayer = [CALayer layer];[self.view.layer addSublayer:_pointLayer];_pointLayer.bounds = CGRectMake(0, 0, 20, 160);_pointLayer.position = self.view.center;return _pointLayer; }
我們這個圖片是一個寬20,高160的圖片,我還是放一個圖吧,免得被罵。。
嗯。。大概就是這個形狀,好的,錨點是以圖層的比例來定義的,我定義的是X軸比例0.5,Y比例0.9,也就是說,這個點大概在X是一半,Y是0.9,就是把這個圖從上到下分成10份,他在第9份那個位置,大概在位置,咳咳。。然後,我們讓他來進行一個旋轉,正常的旋轉應該都是以中心點來旋轉,大概畫面就像孫悟空耍金箍棒一樣,以中心來旋轉
我們來設定一個方法通過定時器來調用它
- (void)start{ // NSCalendar日曆的一個類,可以通過它獲得年月日 時分秒 // NSCalendar // NSDateComponents 組件 fromDate 獲得哪個日期的組件 NSCalendar *calendar = [NSCalendar currentCalendar]; // @property NSInteger hour; // @property NSInteger minute; // @property NSInteger second; NSDateComponents *components = [calendar components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:[NSDate date]]; float s = components.second * 6; //在layer上面添加transform使用的都是CATransform3D //X Y Z是設定繞哪個軸來旋轉的 第一個值是旋轉的角度 self.pointLayer.transform = CATransform3DMakeRotation(s, 0, 0, 1); }
然後我們在viewDidLoad添加一個定時器
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(start) userInfo:nil repeats:YES];
現在他就可以繞點來進行旋轉了
具體每個屬性都可以自己試一下他的效果,然後發一個有助於理解錨點的demo
錨點demo
最後說一下iOS的核心動畫也是通過這個圖層來實現的,下次把連結貼上
再貼上一個圖層效果的一些處理處理圖層特效
我的簡書地址
iOS CALayer視圖圖層