引言函數
相信初接觸到CALayer的人都會遇到如下幾個問題: 爲何修改anchorPoint會移動layer的位置? CALayer的position點是哪一點呢? anchorPoint與position有什麼關係?測試
每個UIView都默認關聯着一個CALayer, UIView有frame、bounds和center三個屬性,CALayer也有相似的屬性,分別爲frame、bounds、position、anchorPoint。那position、anchorPoint是什麼呢?先看看二者的原型,可知都是CGPoint點。spa
@property CGPoint position ;
@property CGPoint anchorPoint ;
anchorPointcode
通常都是先介紹position,再介紹anchorPoint。這裏反過來,先來講說anchorPoint。blog
從一個例子開始入手吧,想象一下,把一張A4白紙用圖釘訂在書桌上,若是訂得不是很緊的話,白紙就能夠沿順時針或逆時針方向圍繞圖釘旋轉,這時候圖釘就起着支點的做用。原型
咱們要解釋的anchorPoint就至關於白紙上的圖釘,它主要的做用就是用來做爲變換的支點,旋轉就是一種變換,相似的還有平移、縮放。it
繼續擴展,很明顯,白紙的旋轉形態隨圖釘的位置不一樣而不一樣,圖釘訂在白紙的正中間與左上角時分別造就了兩種旋轉形態,這是由圖釘(anchorPoint)的位置決定的。io
如何衡量圖釘(anchorPoint)在白紙中的位置呢?class
在iOS中,anchorPoint點的值是用一種相對bounds的比例值來肯定的,在白紙的左上角、右下角,anchorPoint分爲爲(0,0), (1, 1),也就是說anchorPoint是在單元座標空間(同時也是左手座標系)中定義的。擴展
相似地,能夠得出在白紙的中心點、左下角和右上角的anchorPoint爲(0.5,0.5), (0,1), (1,0)。
而後再來看下面圖:
position
確切地說,position是layer中的anchorPoint點在superLayer中的位置座標。所以能夠說, position點是相對suerLayer的,anchorPoint點是相對layer的,二者是相對不一樣的座標空間的一個重合點。
再來看看position的原始定義: The layer’s position in its superlayer’s coordinate space。 中文能夠理解成爲position是layer相對superLayer座標空間的位置,很顯然,這裏的位置是根據anchorPoint來肯定的.
anchorPoint、position、frame
anchorPoint的默認值爲(0.5,0.5),也就是anchorPoint默認在layer的中心點。默認狀況下,使用addSublayer函數添加layer時,若是已知layer的frame值,根據上面的結論,那麼position的值即可以用下面的公式計算:
position.x = frame.origin.x + 0.5 * bounds.size.width; position.y = frame.origin.y + 0.5 * bounds.size.height;
裏面的0.5是由於anchorPoint取默認值,更通用的公式應該是下面的:
position.x = frame.origin.x + anchorPoint.x * bounds.size.width; position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
特別注意
下面再來看另外兩個問題,若是單方面修改layer的position位置,會對anchorPoint有什麼影響呢?修改anchorPoint又如何影響position呢?
根據代碼測試,二者互不影響,受影響的只會是frame.origin,也就是layer座標原點相對superLayer會有所改變。換句話說,frame.origin由position和anchorPoint共同決定,上面的公式能夠變換成下面這樣的:
frame.origin.x = position.x - anchorPoint.x * bounds.size.width; frame.origin.y = position.y - anchorPoint.y * bounds.size.height;
這就解釋了爲何修改anchorPoint會移動layer,由於position不受影響,只能是frame.origin作相應的改變,於是會移動layer。
理解與運用
由於 position點和anchorPoint點是獨立的,本身不會由於另一個的改變而發生變化,可是在實際狀況中,每每有這樣一種需求,我須要修改anchorPoint,但又不想要移動layer也就是不想修改frame.origin,那麼根據前面的公式,就須要position作相應地修改。簡單地推導,能夠獲得下面的公式:
positionNew.x = positionOld.x + (anchorPointNew.x - anchorPointOld.x) * bounds.size.width positionNew.y = positionOld.y + (anchorPointNew.y - anchorPointOld.y) * bounds.size.height
可是在實際使用不必這麼麻煩。修改anchorPoint而不想移動layer,在修改anchorPoint後再從新設置一遍frame就能夠達到目的,這時position就會自動進行相應的改變。寫成函數就是下面這樣的:
- (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{ CGRect oldFrame = view; view.layer.anchorPoint = anchorpoint; view.frame = oldFrame; }
總結
一、position是layer中的anchorPoint在superLayer中的位置座標.
二、互不影響原則:單獨修改position與anchorPoint中任何一個屬性都不影響另外一個屬性。
三、frame、position與anchorPoint有如下關係:
frame.origin.x = position.x - anchorPoint.x * bounds.size.width; frame.origin.y = position.y - anchorPoint.y * bounds.size.height;