Basic CAShapeLayer iOS (P1)

by Hoang Anh Tuan
873 views

Trong lập trình ứng dụng, sẽ có những lúc bạn phải làm việc với các đường thẳng, các hình khối.
Đôi khi chúng quá đơn giản để phải cần cắt ra các image, đôi khi các ứng dụng đòi hỏi các animation, dẫn đến phức tạp thì không thể dùng image được.
CAShapeLayer được dùng để làm việc với các đường thẳng, hình khối 1 cách đơn giản.

Contents:

  • How to draw a line
  • Draw shape with shape layer

How to draw a line?

Học cách vẽ 1 đường thẳng là điều đầu tiên phải học trước khi học vẽ 1 hình khối.
Để vẽ 1 đường thẳng thì cần tối thiểu 2 điểm: điểm đầu và điểm cuối.
UIView có func draw() dùng để vẽ các line:

  • move(to: ): move đến 1 điểm cụ thể để bắt đầu vẽ.
  • addLine(to: ): vẽ 1 đường thẳng đến 1 điểm cụ thể.
    Kết quả thu được:

Để vẽ 1 đường cong, thì apple cung cấp 2 phương thức addCurve() addQuadCurve():

  1. Với func addCurve() thì sẽ vẽ được 1 đường cong với 2 điểm control point là 2 điểm cong.
  2. Với func addQuadCurve() thì sẽ chỉ có 1 điểm control point để tạo điểm cong.
    Kết quả thu được:

Draw shape with shape layer:

Việc sử dụng draw() để vẽ có 1 nhược điểm lớn là nó sẽ bị gọi ngay khi khởi tạo view, và không thể lưu lại. Vậy trong trường hợp bạn muốn vẽ vào 1 thời điểm khác chứ không phải từ đầu? Ta sẽ sử dụng 1 cách phổ biến và đơn giản hơn, là vẽ bằng cách sử dụng CAShapeLayer.

ShapeLayer là gì?

  • Nhìn vào hình trên có thể thấy 1 view sẽ chứa 1 root layer kiẻu CALayer và root layer đó sẽ chứa nhiều sublayer.
  • CAShapeLayer là 1 class kế thừa từ CALayer.
  • Ta dùng CAShapeLayer để tạo ra các custom layer, sau đó sẽ add đề lên root layer của 1 view như là 1 sublayer. Do đó, ta có thể tạo các custom layer tại bất kì thời điểm nào ta muốn và có thể lưu lại.
Thứ tự hiển thị trên view khi add các sublayer

Vẽ các hình khối:

Giờ thì sẽ bắt đầu vẽ các hình khối trên 1 sublayer và add đè lên layer của view.
1 vài hình đơn giản như hình vuông, hình tam giác,… đơn thuần là các nét thẳng thì có thể vẽ đơn giản bằng cách ghép các đường thẳng:

Vẽ hình vuông:

func createSquare() {
        let shapeLayer = CAShapeLayer()
        
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0.0, y: 0.0))
        path.addLine(to: CGPoint(x: 100.0, y: 0.0))
        path.addLine(to: CGPoint(x: 100.0, y: 100.0))
        path.addLine(to: CGPoint(x: 0.0, y: 100.0))
//        path.close() // creating a line segment between the first point and current point
        
        shapeLayer.path = path.cgPath
        shapeLayer.fillColor = UIColor.yellow.cgColor
        shapeLayer.strokeColor = UIColor.red.cgColor
        layer.addSublayer(shapeLayer)
    }
  • Tạo ra 1 shapeLayer.
  • Tạo ra 1 path, 1 path là sự ghép lại của nhiều đường thẳng.
  • Sau khi vẽ xong path, gán path cho shapeLayer.
  • Add đè shapeLayer vừa tạo lên root layer của view.

Đưa đoạn code trên vào hàm init của UIView và chạy thử:
Kết quả thu được:

Hàm close() ở trên được dùng để tạo ra 1 đường thẳng nối điểm hiện tại và điểm đầu tiên khi bắt đầu vẽ.
-> Uncomment hàm close() ở trên và run sẽ thu được kết quả:

Ngoài ra cũng có thể dùng 1 hàm addLine() thay cho hàm close() để nối 2 điểm.

Hình bầu dục:

Để vẽ hình bầu dục, sử dụng hàm UIBezierPath(ovalIn: CGRect):

private func createOval() {
    let shapeLayer = CAShapeLayer()
        
    shapeLayer.lineWidth = 2.0
    shapeLayer.fillColor = nil
    shapeLayer.strokeColor = UIColor.red.cgColor
    let openCirclePath = UIBezierPath(ovalIn: self.bounds)
        
    shapeLayer.path = openCirclePath.cgPath        
    layer.addSublayer(shapeLayer)
}

Bạn cung cấp 1 frame để vẽ hình bầu dục trong đó, ở đây mình sẽ dùng view.bounds. Kết quả thu được:

Vẽ hình tròn:

Để vẽ 1 hình tròn thì trước hết cần phải biết các góc trong 1 hình tròn:

Sau đó chỉ cần dùng hàm được cung cấp sẵn:

private func createCircle() {
    let shapeLayer = CAShapeLayer()
        
    shapeLayer.lineWidth = 2.0
    shapeLayer.fillColor = nil
    shapeLayer.strokeColor = UIColor.red.cgColor
    let openCirclePath = UIBezierPath(arcCenter: CGPoint(x: 60.0, y: 60.0),
                                      radius: 60.0,
                                      startAngle: 0.0,
                                      endAngle: CGFloat.pi * 2,
                                      clockwise: true)
        
    shapeLayer.path = openCirclePath.cgPath
    layer.addSublayer(shapeLayer)
}
  • arcCenter: tâm hình tròn
  • radius: Bán kính
  • startAngle, endAngle: Điểm bắt đầu và điểm kết thúc.
  • clockWise: có vẽ theo chiều kim đồng hồ không.

Tùy vào bạn muốn vẽ 1 góc bao nhiêu độ mà thay 1 radius thích hợp.
Kết quả thu được:

Bài viết này đã tóm tắt về cách vẽ hình cơ bản.
Ở bài viết sau về shapeLayer, sẽ nói về ShapeLayer Attribute và ShapeLayer Animation.

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.