2015-12-23 30 views
13

之前寫這個問題,我已經如何在CALayer上進行轉換?

看到 this detailed CALayer tutorial石英2D編程指南
  • 下載在閱讀Transforms documentation和運行LayerPlayer project

    但是,我仍然無法理解如何做一個基本的變換。尋找翻譯,旋轉和縮放的解釋和簡單例子一直很困難。

    今天我終於決定坐下來做一個測試項目,並把它們弄清楚。我的答案如下。

    注:

    • 我只做斯威夫特,但如果別人要添加的Objective-C代碼,是我的客人。
    • 在這一點上,我只關心理解2D變換。
  • 回答

    51

    基礎

    有許多不同的轉換,你可以在層上做的,但基本的有

    • 翻譯(移動)
    • 規模
    • 旋轉

    enter image description here

    要對CALayer執行變換,請將圖層的transform屬性設置爲CATransform3D類型。例如,翻譯層,你會做這樣的事情:

    myLayer.transform = CATransform3DMakeTranslation(20, 30, 0) 
    

    Make在名稱中使用創建初始轉換:CATransform3D 翻譯。後續應用的轉換省略了Make。見,例如,這種旋轉再平移:

    let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0/180.0, 20, 20, 0) 
    myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0) 
    

    現在我們有如何使改造的基礎上,讓我們來看看如何做到每一個的一些例子。不過,首先,我會展示如何設置該項目,以防您也想玩弄它。

    設置

    對於我設置的單一視圖的應用,用淺藍色背景到故事板加入一個UIView以下實施例。我掛接視圖以用下面的代碼視圖控制器:

    import UIKit 
    
    class ViewController: UIViewController { 
    
        var myLayer = CATextLayer() 
        @IBOutlet weak var myView: UIView! 
    
        override func viewDidLoad() { 
         super.viewDidLoad() 
    
         // setup the sublayer 
         addSubLayer() 
    
         // do the transform 
         transformExample() 
        } 
    
        func addSubLayer() { 
         myLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 40) 
         myLayer.backgroundColor = UIColor.blue.cgColor 
         myLayer.string = "Hello" 
         myView.layer.addSublayer(myLayer) 
        } 
    
        //******** Replace this function with the examples below ******** 
    
        func transformExample() { 
    
         // add transform code here ... 
    
    
        } 
    
    } 
    

    There are many different kinds of CALayer,但我選擇使用CATextLayer使得變換會更加清楚視覺。

    翻譯

    翻譯變換移動圖層。基本語法是

    CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat) 
    

    其中tx是x座標的變化,ty是在y中的變化,並且是tz在z上的變化。

    enter image description here

    在iOS系統中的座標系的原點在左上角,所以如果我們想移動層90點到右側和50分的情況下,我們會做到以下幾點:

    myLayer.transform = CATransform3DMakeTranslation(90, 50, 0) 
    

    • 請記住,您可以將其粘貼到上述項目代碼中的transformExample()方法中。
    • 由於我們只是在這裏處理兩個維度,因此tz設置爲0
    • 上圖中的紅線從原始位置的中心到新位置的中心。這是因爲變換是相對於錨點完成的,默認情況下錨點位於圖層的中心。

    量表

    的尺度變換拉伸或squishes的層。基本語法是

    CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat) 
    

    其中sxsy,和sz是數字,通過該按比例繪製(乘)在x,y和z分別座標。

    enter image description here

    如果我們想一半的寬度和三重高度,我們會做以下

    myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0) 
    

    • 由於我們是隻在兩個方面工作,我們只需將z座標乘以1.0即可保持不變。
    • 上圖中的紅點表示錨點。注意縮放是如何與錨點相關的。也就是說,一切都要麼拉向或遠離定位點。

    旋轉

    旋轉變換繞錨點的層(該層的默認的中心)。基本語法是

    CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat) 
    

    其中angle是弧度的角度,該層應該旋轉和xy,和z是圍繞其旋轉的軸。將座標軸設置爲0將取消圍繞該特定軸的旋轉。

    enter image description here

    如果我們想層順時針旋轉30度,我們將做到以下幾點:

    let degrees = 30.0 
    let radians = CGFloat(degrees * Double.pi/180) 
    myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0) 
    

    • 由於我們是在兩個維度上工作,我們只想要xy平面圍繞z軸旋轉。因此,我們將xy設置爲0.0並將z設置爲1.0
    • 這使得圖層順時針旋轉。我們可以通過將z設置爲-1.0來逆時針旋轉。
    • 紅點顯示錨點的位置。旋轉是在錨點周圍完成的。

    多個變換

    爲了多變換結合,我們可以使用concatination這樣

    CATransform3DConcat(a: CATransform3D, b: CATransform3D) 
    

    不過,我們會只是做了一個又一個。第一個轉換將使用其名稱中的Make。以下轉換不會使用Make,但它們將以前一個轉換爲參數。

    enter image description here

    這一次,我們結合這三個以前的變換。

    let degrees = 30.0 
    let radians = CGFloat(degrees * Double.pi/180) 
    
    // translate 
    var transform = CATransform3DMakeTranslation(90, 50, 0) 
    
    // rotate 
    transform = CATransform3DRotate(transform, radians, 0.0, 0.0, 1.0) 
    
    // scale 
    transform = CATransform3DScale(transform, 0.5, 3.0, 1.0) 
    
    // apply the transforms 
    myLayer.transform = transform 
    

    • 的變換在做事情的順序。
    • 一切都是與錨點(紅點)有關。

    約錨點注和位置

    我們盡了所有變換上述不改變錨點。有時候有必要改變它,但是,如果你想圍繞中心以外的其他點旋轉。但是,這可能有點棘手。

    定位點和位置都在同一個地方。定位點表示爲圖層座標系統的一個單位(默認值爲0.5, 0.5),位置用超級座標系統表示。它們可以這樣設置

    myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0) 
    myLayer.position = CGPoint(x: 50, y: 50) 
    

    如果只設置錨點而不改變位置,然後在框架的變化,使得位置將是在正確的位置。或者更準確地說,根據新的錨點和舊的位置重新計算框架。這通常會帶來意想不到的結以下兩篇文章對此進行了精彩的討論。

    參見