2015-12-23 29 views
13

Trước khi viết câu hỏi này, tôi đãLàm cách nào để thực hiện các phép biến đổi trên một CALayer?

Tuy nhiên, tôi vẫn gặp sự cố khi hiểu cách thực hiện các biến đổi cơ bản trên lớp. Tìm kiếm các giải thích và các ví dụ đơn giản về dịch, xoay và mở rộng đã khó.

Hôm nay tôi cuối cùng đã quyết định ngồi xuống, thực hiện một dự án thử nghiệm và tìm ra chúng. Câu trả lời của tôi là dưới đây.

Ghi chú:

  • tôi chỉ làm Swift, nhưng nếu ai đó muốn thêm mã Objective-C, được khách của tôi.
  • Tại thời điểm này, tôi chỉ quan tâm đến việc hiểu các biến đổi 2D.

Trả lời

51

Khái niệm cơ bản

Có một số khác nhau biến đổi bạn có thể làm trên một lớp, nhưng những cái cơ bản là

  • dịch (di chuyển)
  • quy mô
  • xoay

enter image description here

Để thực hiện các biến đổi trên CALayer, bạn đặt thuộc tính transform của lớp thành loại CATransform3D. Ví dụ, để dịch một lớp, bạn sẽ làm một cái gì đó như thế này:

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

Từ Make được sử dụng trong tên để tạo ban đầu chuyển đổi: CATransform3D Hãy dịch. Các biến đổi tiếp theo được áp dụng bỏ qua Make. Xem, ví dụ, luân chuyển này theo sau là một dịch:

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

Bây giờ chúng ta có cơ sở như thế nào để thực hiện một thay đổi, chúng ta hãy xem xét một số ví dụ về làm thế nào để làm mỗi một. Đầu tiên, mặc dù, tôi sẽ cho thấy cách tôi thiết lập dự án trong trường hợp bạn muốn chơi xung quanh với nó, quá.

Cài đặt

Đối với các ví dụ sau tôi thiết lập một View Single ứng dụng và thêm một UIView với một nền màu xanh nhạt để kịch bản này.Tôi nối quan điểm với bộ điều khiển vùng đang xem với đoạn mã sau:

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, nhưng tôi đã chọn để sử dụng CATextLayer để các biến đổi sẽ được rõ ràng hơn hình ảnh.

Dịch

Biến đổi dịch chuyển lớp. Cú pháp cơ bản là

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

nơi tx là sự thay đổi trong x tọa độ, ty là sự thay đổi trong y, và tz là sự thay đổi trong z.

Ví dụ

enter image description here

Trong iOS nguồn gốc của hệ tọa độ là ở phía trên bên trái, vì vậy nếu chúng ta muốn di chuyển các lớp 90 điểm bên phải và 50 điểm xuống, chúng ta sẽ làm như sau:

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

Ghi chú

  • Hãy nhớ rằng bạn có thể dán mã này vào phương thức transformExample() trong mã dự án ở trên.
  • Vì chúng tôi sẽ xử lý hai thứ nguyên ở đây, tz được đặt thành 0.
  • Đường màu đỏ trong hình ở trên đi từ trung tâm của vị trí ban đầu đến trung tâm của vị trí mới. Đó là bởi vì biến đổi được thực hiện liên quan đến điểm neo và điểm neo theo mặc định là ở trung tâm của lớp.

Scale

Quy mô chuyển hóa trải dài hoặc squishes lớp. Cú pháp cơ bản là

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

nơi sx, sy, và sz là những con số mà theo đó để mở rộng quy mô (nhân) x, y, và z phối tương ứng.

Ví dụ

enter image description here

Nếu chúng ta muốn một nửa chiều rộng và gấp ba lần chiều cao, chúng ta sẽ làm như sau

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

Ghi chú

  • Vì chúng tôi là chỉ làm việc theo hai chiều, chúng ta chỉ nhân các tọa độ z với 1.0 để chúng không bị ảnh hưởng.
  • Dấu chấm màu đỏ trong hình trên thể hiện điểm neo. Lưu ý cách chia tỷ lệ được thực hiện liên quan đến điểm neo. Đó là, mọi thứ được kéo dài về phía hoặc ra khỏi điểm neo.

Xoay

Vòng xoay chuyển xoay lớp xung quanh điểm neo (trung tâm của lớp theo mặc định). Cú pháp cơ bản là

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

nơi angle là góc theo radian rằng lớp nên được luân chuyển và x, y, và z là các trục về để xoay. Đặt trục thành 0 sẽ hủy vòng xoay quanh trục cụ thể đó.

Ví dụ

enter image description here

Nếu chúng ta muốn xoay một lớp chiều kim đồng hồ 30 độ, chúng ta sẽ làm như sau:

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

Ghi chú

  • Vì chúng tôi là làm việc theo hai lần, chúng tôi chỉ muốn mặt phẳng xy được xoay quanh trục z. Do đó, chúng tôi đặt xy đến 0.0 và đặt z thành 1.0.
  • Điều này xoay lớp theo chiều kim đồng hồ. Chúng tôi có thể xoay ngược chiều kim đồng hồ bằng cách đặt z thành -1.0.
  • Dấu chấm màu đỏ cho biết vị trí điểm neo. Vòng xoay được thực hiện xung quanh điểm neo.

Nhiều biến

Để kết hợp nhiều biến đổi chúng ta có thể sử dụng bởi ghép như thế này

CATransform3DConcat(a: CATransform3D, b: CATransform3D) 

Tuy nhiên, chúng tôi sẽ chỉ làm cái khác. Biến đổi đầu tiên sẽ sử dụng tên Make. Các biến đổi sau sẽ không sử dụng Make, nhưng chúng sẽ lấy biến đổi trước đó làm tham số.

Ví dụ

enter image description here

Lần này chúng tôi kết hợp cả ba của biến đổi trước.

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 

Ghi chú

  • Trình tự rằng biến đổi được thực hiện trong các vấn đề.
  • Mọi thứ đã được thực hiện liên quan đến điểm neo (chấm đỏ).

Lưu ý về Anchor Point và Chức vụ

Chúng tôi đã làm tất cả biến đổi của chúng tôi ở trên mà không thay đổi điểm neo.Đôi khi nó là cần thiết để thay đổi nó, mặc dù, giống như nếu bạn muốn xoay quanh một số điểm khác bên cạnh trung tâm. Tuy nhiên, điều này có thể hơi phức tạp một chút.

Điểm neo và vị trí đều ở cùng một vị trí. Điểm neo được biểu diễn dưới dạng đơn vị hệ tọa độ của lớp (mặc định là 0.5, 0.5) và vị trí được thể hiện trong hệ tọa độ của siêu lớp. Chúng có thể được đặt như thế này

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

Nếu bạn chỉ đặt điểm neo mà không thay đổi vị trí, thì khung sẽ thay đổi để vị trí sẽ nằm đúng vị trí. Hoặc chính xác hơn, khung được tính toán lại dựa trên điểm neo mới và vị trí cũ. Điều này thường cho kết quả không mong muốn. Hai bài viết sau đây có một cuộc thảo luận tuyệt vời về điều này.

Xem thêm

Các vấn đề liên quan