徹底理解position與anchorPoint

引言
相信初接觸到CALayer的人都會(huì)遇到以下幾個(gè)問題: 為什么修改anchorPoint會(huì)移動(dòng)layer的位置宜狐? CALayer的position點(diǎn)是哪一點(diǎn)呢? anchorPoint與position有什么關(guān)系?
我也迷惑過,找過網(wǎng)上的教程途茫,大部分都是復(fù)制粘貼的速那,有些是翻譯的文章但很有問題劳淆,看得似懂非懂凉翻,還是自己寫代碼徹底弄懂了,做點(diǎn)筆記吧内颗。
每一個(gè)UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個(gè)CALayer, UIView有frame钧排、bounds和center三個(gè)屬性,CALayer也有類似的屬性均澳,分別為frame恨溜、bounds、position找前、anchorPoint筒捺。frame和bounds比較好理解,bounds可以視為x坐標(biāo)和y坐標(biāo)都為0的frame纸厉,那position系吭、anchorPoint是什么呢?先看看兩者的原型颗品,可知都是CGPoint點(diǎn)肯尺。
@property CGPoint position @property CGPoint anchorPoint
anchorPoint
一般都是先介紹position沃缘,再介紹anchorPoint。我這里反過來则吟,先來說說anchorPoint槐臀。
從一個(gè)例子開始入手吧,想象一下氓仲,把一張A4白紙用圖釘訂在書桌上水慨,如果訂得不是很緊的話,白紙就可以沿順時(shí)針或逆時(shí)針方向圍繞圖釘旋轉(zhuǎn)敬扛,這時(shí)候圖釘就起著支點(diǎn)的作用晰洒。我們要解釋的anchorPoint就相當(dāng)于白紙上的圖釘,它主要的作用就是用來作為變換的支點(diǎn)啥箭,旋轉(zhuǎn)就是一種變換谍珊,類似的還有平移、縮放急侥。
繼續(xù)擴(kuò)展砌滞,很明顯,白紙的旋轉(zhuǎn)形態(tài)隨圖釘?shù)奈恢貌煌煌倒郑瑘D釘訂在白紙的正中間與左上角時(shí)分別造就了兩種旋轉(zhuǎn)形態(tài)贝润,這是由圖釘(anchorPoint)的位置決定的。如何衡量圖釘(anchorPoint)在白紙中的位置呢铝宵?在iOS中题暖,anchorPoint點(diǎn)的值是用一種相對(duì)bounds的比例值來確定的,在白紙的左上角捉超、右下角,anchorPoint分為為(0,0), (1, 1)唯绍,也就是說anchorPoint是在單元坐標(biāo)空間(同時(shí)也是左手坐標(biāo)系)中定義的拼岳。類似地,可以得出在白紙的中心點(diǎn)况芒、左下角和右上角的anchorPoint為(0.5,0.5), (0,1), (1,0)惜纸。
然后再來看下面兩張圖,注意圖中分iOS與MacOS绝骚,因?yàn)閮烧叩淖鴺?biāo)系不相同耐版,iOS使用左手坐標(biāo)系,坐標(biāo)原點(diǎn)在左上角压汪,MacOS使用右手坐標(biāo)系粪牲,原點(diǎn)在左下角,我們看iOS部分即可止剖。

Optional title
圖1
Optional title
圖2
像UIView有superView與subView的概念一樣腺阳,CALayer也有superLayer與layer的概念落君,前面說到的白紙和圖中的矩形可以理解為layer,書桌和圖中矩形以外的坐標(biāo)系可以理解成superLayer亭引。如果各自以左上角為原點(diǎn)绎速,則在圖中有相對(duì)的兩個(gè)坐標(biāo)空間。
position
在圖1中焙蚓,anchorPoint有(0.5,0.5)和(0,0)兩種情況纹冤,分別為矩形的中心點(diǎn)與原點(diǎn)。那么购公,這兩個(gè)anchorPoint在superLayer中的實(shí)際位置分別為多少呢萌京?簡(jiǎn)單計(jì)算一下就可以得到(100, 100)和(40, 60),把這兩個(gè)值分別與各自的position值比較君丁,發(fā)現(xiàn)完全一致枫夺,該不會(huì)是巧合?
這時(shí)候可以大膽猜測(cè)一下绘闷,position是不是就是anchorPoint在superLayer中的位置呢橡庞?答案是確定的,更確切地說印蔗,position是layer中的anchorPoint點(diǎn)在superLayer中的位置坐標(biāo)扒最。因此可以說, position點(diǎn)是相對(duì)suerLayer的,anchorPoint點(diǎn)是相對(duì)layer的华嘹,兩者是相對(duì)不同的坐標(biāo)空間的一個(gè)重合點(diǎn)吧趣。
再來看看position的原始定義: The layer’s position in its superlayer’s coordinate space。 中文可以理解成為position是layer相對(duì)superLayer坐標(biāo)空間的位置耙厚,很顯然强挫,這里的位置是根據(jù)anchorPoint來確定的。
圖2中是矩形沿不同的anchorPoint點(diǎn)旋轉(zhuǎn)的形態(tài)薛躬,這就是類似于剛才講的圖釘訂在白紙的正中間與左上角時(shí)分別造就了兩種旋轉(zhuǎn)形態(tài)俯渤。
anchorPoint、position型宝、frame
anchorPoint的默認(rèn)值為(0.5,0.5)八匠,也就是anchorPoint默認(rèn)在layer的中心點(diǎn)。默認(rèn)情況下趴酣,使用addSublayer函數(shù)添加layer時(shí)梨树,如果已知layer的frame值,根據(jù)上面的結(jié)論岖寞,那么position的值便可以用下面的公式計(jì)算:
12
position.x = frame.origin.x + 0.5 * bounds.size.width抡四; position.y = frame.origin.y + 0.5 * bounds.size.height;

里面的0.5是因?yàn)閍nchorPoint取默認(rèn)值仗谆,更通用的公式應(yīng)該是下面的:
12
position.x = frame.origin.x + anchorPoint.x * bounds.size.width床嫌; position.y = frame.origin.y + anchorPoint.y * bounds.size.height跨释;

下面再來看另外兩個(gè)問題,如果單方面修改layer的position位置厌处,會(huì)對(duì)anchorPoint有什么影響呢鳖谈?修改anchorPoint又如何影響position呢? 根據(jù)代碼測(cè)試阔涉,兩者互不影響缆娃,受影響的只會(huì)是frame.origin,也就是layer坐標(biāo)原點(diǎn)相對(duì)superLayer會(huì)有所改變瑰排。換句話說贯要,frame.origin由position和anchorPoint共同決定,上面的公式可以變換成下面這樣的:
12
frame.origin.x = position.x - anchorPoint.x * bounds.size.width椭住; frame.origin.y = position.y - anchorPoint.y * bounds.size.height崇渗;

這就解釋了為什么修改anchorPoint會(huì)移動(dòng)layer,因?yàn)閜osition不受影響京郑,只能是frame.origin做相應(yīng)的改變宅广,因而會(huì)移動(dòng)layer。
理解與運(yùn)用
在Apple doc對(duì)frame的描述中有這么一句話:
Layers have an implicit frame that is a function of the position, bounds, anchorPoint, and transform properties.
可以看到我們推導(dǎo)的公式基本符合這段描述些举,只不過還缺少了transform跟狱,加上transform的話就比較復(fù)雜,這里就不展開講了户魏。
Apple doc中還有一句描述是這樣的:
When you specify the frame of a layer, position is set relative to the anchor point. When you specify the position of the layer, bounds is set relative to the anchor point.
大意是:當(dāng)你設(shè)置圖層的frame屬性的時(shí)候驶臊,position根據(jù)錨點(diǎn)(anchorPoint)的值來確定,而當(dāng)你設(shè)置圖層的position屬性的時(shí)候叼丑,bounds會(huì)根據(jù)錨點(diǎn)(anchorPoint)來確定关翎。
這段翻譯的上半句根據(jù)前面的公式容易理解,后半句可能就有點(diǎn)令人迷惑了鸠信,當(dāng)修改position時(shí)纵寝,bounds的width與height會(huì)隨之修改嗎?其實(shí),position是點(diǎn)症副,bounds是矩形,根據(jù)錨點(diǎn)(anchorPoint)來確定的只是它們的位置政基,而不是內(nèi)部屬性贞铣。所以,上面這段英文這么翻譯就容易理解了:
當(dāng)你設(shè)置圖層的frame屬性的時(shí)候沮明,position點(diǎn)的位置(也就是position坐標(biāo))根據(jù)錨點(diǎn)(anchorPoint)的值來確定辕坝,而當(dāng)你設(shè)置圖層的position屬性的時(shí)候,bounds的位置(也就是frame的orgin坐標(biāo))會(huì)根據(jù)錨點(diǎn)(anchorPoint)來確定荐健。
在實(shí)際情況中酱畅,可能還有這樣一種需求琳袄,我需要修改anchorPoint,但又不想要移動(dòng)layer也就是不想修改frame.origin纺酸,那么根據(jù)前面的公式窖逗,就需要position做相應(yīng)地修改。簡(jiǎn)單地推導(dǎo)餐蔬,可以得到下面的公式:
12
positionNew.x = positionOld.x + (anchorPointNew.x - anchorPointOld.x) * bounds.size.width positionNew.y = positionOld.y + (anchorPointNew.y - anchorPointOld.y) * bounds.size.height

但是在實(shí)際使用沒必要這么麻煩碎紊。修改anchorPoint而不想移動(dòng)layer,在修改anchorPoint后再重新設(shè)置一遍frame就可以達(dá)到目的樊诺,這時(shí)position就會(huì)自動(dòng)進(jìn)行相應(yīng)的改變仗考。寫成函數(shù)就是下面這樣的:
12345

  • (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{ CGRect oldFrame = view; view.layer.anchorPoint = anchorpoint; view.frame = oldFrame;}

總結(jié)
1、position是layer中的anchorPoint在superLayer中的位置坐標(biāo)词爬。 2秃嗜、互不影響原則:?jiǎn)为?dú)修改position與anchorPoint中任何一個(gè)屬性都不影響另一個(gè)屬性。 3顿膨、frame锅锨、position與anchorPoint有以下關(guān)系:
12
frame.origin.x = position.x - anchorPoint.x * bounds.size.width; frame.origin.y = position.y - anchorPoint.y * bounds.size.height虽惭;

第2條的互不影響原則還可以這樣理解:position與anchorPoint是處于不同坐標(biāo)空間中的重合點(diǎn)橡类,修改重合點(diǎn)在一個(gè)坐標(biāo)空間的位置不影響該重合點(diǎn)在另一個(gè)坐標(biāo)空間中的位置。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芽唇,一起剝皮案震驚了整個(gè)濱河市顾画,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌匆笤,老刑警劉巖研侣,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異炮捧,居然都是意外死亡庶诡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門咆课,熙熙樓的掌柜王于貴愁眉苦臉地迎上來末誓,“玉大人,你說我怎么就攤上這事书蚪±瑁” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵殊校,是天一觀的道長(zhǎng)晴玖。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么呕屎? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任让簿,我火速辦了婚禮,結(jié)果婚禮上秀睛,老公的妹妹穿的比我還像新娘尔当。我一直安慰自己,他們只是感情好琅催,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布居凶。 她就那樣靜靜地躺著,像睡著了一般藤抡。 火紅的嫁衣襯著肌膚如雪侠碧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天缠黍,我揣著相機(jī)與錄音弄兜,去河邊找鬼。 笑死瓷式,一個(gè)胖子當(dāng)著我的面吹牛替饿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贸典,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼视卢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了廊驼?” 一聲冷哼從身側(cè)響起据过,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎妒挎,沒想到半個(gè)月后绳锅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酝掩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年鳞芙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片期虾。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡原朝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镶苞,到底是詐尸還是另有隱情喳坠,我是刑警寧澤,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布宾尚,位于F島的核電站丙笋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏煌贴。R本人自食惡果不足惜御板,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牛郑。 院中可真熱鬧怠肋,春花似錦、人聲如沸淹朋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽础芍。三九已至杈抢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仑性,已是汗流浹背惶楼。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诊杆,地道東北人歼捐。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像晨汹,于是被迫代替她去往敵國(guó)和親豹储。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容