一般都是先介紹position,再介紹anchorPoint。我這里反過來,先來說說anchorPoint。
從一個例子開始入手吧,想象一下,把一張A4白紙用圖釘訂在書桌上,如果訂得不是很緊的話,白紙就可以沿順時針或逆時針方向圍繞圖釘旋轉,這時候圖釘就起著支點的作用。我們要解釋的anchorPoint就相當于白紙上的圖釘,它主要的作用就是用來作為變換的支點,旋轉就是一種變換,類似的還有平移、縮放。
繼續擴展。很明顯,白紙的旋轉形態隨圖釘的位置不同而不同,圖釘訂在白紙的正中間與左上角時分別造就了兩種旋轉形態,這是由圖釘(anchorPoint)的位置決定的。如何衡量圖釘(anchorPoint)在白紙中的位置呢?在iOS中,anchorPoint點的值是用一種相對bounds的比例值來確定的,在白紙的左上角、右下角,anchorPoint分為為(0,0),(1, 1)。類似地,可以得出在白紙的中心點、左下角和右上角的anchorPoint為(0.5,0.5), (0,1), (1,0)。
然后再來看下面兩張圖,注意圖中分iOS與MacOS,因為兩者的坐標系不相同,iOS坐標原點在左上角,MacOS坐標原點在左下角,我們看iOS部分即可。
在上面這張圖中,anchorPoint有(0.5,0.5)和(0,0)兩種情況,分別為矩形的中心點與原點。那么,這兩個anchorPoint在superLayer中的實際位置分別為多少呢?簡單計算一下就可以得到(100, 100)和(40, 60),把這兩個值分別與各自的position值比較,發現完全一致,該不會是巧合?
這時候可以大膽猜測一下,position是不是就是anchorPoint在superLayer中的位置呢?答案是確定的,更確切地說,position是layer中的anchorPoint點在superLayer中的位置坐標。因此可以說, position點是相對suerLayer的,anchorPoint點是相對layer的,兩者是相對不同的坐標空間的一個重合點。
再來看看position的原始定義:
The layer’s position in its superlayer’s coordinate space。
中文可以理解成為position是layer相對superLayer坐標空間的位置。所以請記住這個結論:position的位置是根據anchorPoint來確定的。
anchorPoint通常被翻譯成錨點,其實可以理解為同一個東西。它具體的表現可以看下面這張圖,其實就是作為旋轉、縮放等空間變化提供了中心點。這就類似于剛才講的圖釘訂在白紙的正中間與左上角時分別造就了兩種旋轉形態。
3.anchorPoint、position、frame之間的關系
3.1 —— 三者之間的計算公式
聰明的你其實已經可以在第二點中已經找到這三者之間的關系了,現在我只不過是特地拿出來正式講一下。
anchorPoint的默認值為(0.5,0.5),也就是anchorPoint默認在layer的中心點。計算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;
3.2 —— 第二個問題
下面再來看另外兩個問題,如果單方面修改layer的position位置,會對anchorPoint有什么影響呢?修改anchorPoint又如何影響position呢?
**根據代碼測試,兩者互不影響,受影響的只會是frame.origin。**
所以我們又可以得出今天的第二個結論:anchorPoint和position互不影響,故受影響的只有frame。
現在又可以得出一個換湯不換藥的裝逼公式:
frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;
PS:這就解釋了為什么修改anchorPoint會移動layer,因為position不受影響,只能是frame.origin做相應的改變,因而會移動layer。
3.3 —— 優化
在實際情況中,可能還有這樣一種需求,我需要修改anchorPoint而不想移動layer,在修改anchorPoint后再重新設置一遍frame就可以達到目的,這時position就會自動進行相應的改變。
代碼:
- (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{
CGRect oldFrame = view.frame;
view.layer.anchorPoint = anchorpoint;
view.frame = oldFrame;
}
總結
1、position是layer中的anchorPoint在superLayer中的位置坐標。
2、互不影響原則:單獨修改position與anchorPoint中任何一個屬性都不影響另一個屬性。
3、frame、position與anchorPoint有以下關系:
frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;