2015-05-20 35 views
7

Tôi muốn tạo hiệu ứng hình dạng khi nó chuyển từ hình tròn sang hình tam giác góc tròn.Tạo hình tròn CAShapeLayer thành hình tam giác góc tròn

TL; DR: Làm cách nào để tạo ảnh động's path giữa hai hình CGPath? Tôi biết rằng họ cần phải có cùng một số điểm kiểm soát, nhưng tôi nghĩ rằng tôi đang làm điều đó - có gì sai với mã này?

Các trạng thái đầu và cuối sẽ giống như thế này: transition http://clrk.it/4vJS+

Đây là những gì tôi đã cố gắng cho đến nay: Tôi đang sử dụng một CAShapeLayer, và hiệu ứng động một sự thay đổi trong tài sản path của nó.

Theo (tôi nhấn mạnh) documentation:

Đối tượng con đường có thể được hoạt hình sử dụng bất kỳ lớp con cụ thể của CAPropertyAnimation. Đường dẫn sẽ nội suy như một sự pha trộn tuyến tính của các điểm "trên mạng"; Điểm "ngoại tuyến" có thể được nội suy phi tuyến tính (ví dụ: để duy trì tính liên tục của đạo hàm của đường cong). Nếu hai đường dẫn có số điểm hoặc đoạn điều khiển khác nhau thì kết quả sẽ không được xác định.

Để cố gắng thu được hình tròn và hình tam giác có cùng số điểm kiểm soát, tôi đã tạo cho chúng cả hai hình dạng bốn cạnh: hình tròn là hình chữ nhật được làm tròn và tam giác là "ẩn" một điểm kiểm soát thứ tư ở một bên.

Dưới đây là mã của tôi:

self.view.backgroundColor = .blueColor() 

//CREATE A CASHAPELAYER 
let shape = CAShapeLayer() 
shape.frame = CGRect(x: 50, y: 50, width: 200, height: 200) 
shape.fillColor = UIColor.redColor().CGColor 
self.view.layer.addSublayer(shape) 

let bounds = shape.bounds 

//CREATE THE SQUIRCLE 
let squareRadius: CGFloat = CGRectGetWidth(shape.bounds)/2 

let topCorner = CGPointMake(bounds.midX, bounds.minY) 
let rightCorner = CGPointMake(bounds.maxX, bounds.midY) 
let bottomCorner = CGPointMake(bounds.midX, bounds.maxY) 
let leftCorner = CGPointMake(bounds.minX, bounds.midY) 

let squarePath = CGPathCreateMutable() 
let squareStartingPoint = midPoint(leftCorner, point2: topCorner) 
CGPathMoveToPoint(squarePath, nil, squareStartingPoint.x, squareStartingPoint.y) 
addArcToPoint(squarePath, aroundPoint: topCorner, onWayToPoint: rightCorner, radius: squareRadius) 
addArcToPoint(squarePath, aroundPoint: rightCorner, onWayToPoint: bottomCorner, radius: squareRadius) 
addArcToPoint(squarePath, aroundPoint: bottomCorner, onWayToPoint: leftCorner, radius: squareRadius) 
addArcToPoint(squarePath, aroundPoint: leftCorner, onWayToPoint: topCorner, radius: squareRadius) 
CGPathCloseSubpath(squarePath) 
let square = UIBezierPath(CGPath: squarePath) 

//CREATE THE (FAKED) TRIANGLE 
let triangleRadius: CGFloat = 25.0 

let trianglePath = CGPathCreateMutable() 
let triangleStartingPoint = midPoint(topCorner, point2: rightCorner) 

let startingPoint = midPoint(topCorner, point2: leftCorner) 
CGPathMoveToPoint(trianglePath, nil, startingPoint.x, startingPoint.y) 
let cheatPoint = midPoint(topCorner, point2:bottomCorner) 
addArcToPoint(trianglePath, aroundPoint: topCorner, onWayToPoint: cheatPoint, radius: triangleRadius) 
addArcToPoint(trianglePath, aroundPoint: cheatPoint, onWayToPoint: bottomCorner, radius: triangleRadius) 
addArcToPoint(trianglePath, aroundPoint: bottomCorner, onWayToPoint: leftCorner, radius: triangleRadius) 
addArcToPoint(trianglePath, aroundPoint: leftCorner, onWayToPoint: topCorner, radius: triangleRadius) 
CGPathCloseSubpath(trianglePath) 
let triangle = UIBezierPath(CGPath: trianglePath) 


shape.path = square.CGPath 

... và sau này, trong viewDidAppear:

let animation = CABasicAnimation(keyPath: "path") 
animation.fromValue = self.square.CGPath 
animation.toValue = self.triangle.CGPath 
animation.duration = 3 
self.shape.path = self.triangle.CGPath 
self.shape.addAnimation(animation, forKey: "animationKey") 

Tôi có hai chức năng nhỏ nhanh chóng để làm cho mã dễ đọc hơn:

func addArcToPoint(path: CGMutablePath!, aroundPoint: CGPoint, onWayToPoint: CGPoint, radius: CGFloat) { 
    CGPathAddArcToPoint(path, nil, aroundPoint.x, aroundPoint.y, onWayToPoint.x, onWayToPoint.y, radius) 
} 

func midPoint(point1: CGPoint, point2: CGPoint) -> CGPoint { 
    return CGPointMake((point1.x + point2.x)/2, (point1.y + point2.y)/2) 
} 

Kết quả hiện tại của tôi trông giống như sau:

triangle-to-square

LƯU Ý: Tôi đang cố gắng để xây dựng hình tròn ra một hình vuông rất lạ, trong một nỗ lực để có được cùng một số điểm kiểm soát trong hình vector shape. Trong ảnh GIF ở trên, bán kính góc đã được giảm để làm cho phép biến đổi hiển thị rõ hơn.

Bạn nghĩ điều gì đang diễn ra? Làm thế nào tôi có thể đạt được hiệu ứng này?

+0

cố gắng tạo cả hai hình dạng với nhiều đoạn đường thẳng thay thế? – nielsbot

+0

thực sự, bạn có chắc là bạn đang sử dụng addArcToPoint() đúng không? – nielsbot

+0

(Tôi không htink tham số * path * để thêmArcToPoint() thành tùy chọn) – nielsbot

Trả lời

6

Bạn không kết thúc với cùng số điểm kiểm soát vì addArcToPoint() bỏ qua tạo phân đoạn đường nếu điểm hiện tại của đường dẫn và đối số đầu tiên của đường dẫn bằng nhau.

Từ tài liệu của nó (tôi nhấn mạnh):

Nếu điểm hiện tại và các điểm tiếp xúc đầu tiên của vòng cung (điểm khởi đầu) không bằng nhau, thạch anh gắn thêm một đoạn đường thẳng từ hiện tại trỏ đến điểm tiếp tuyến đầu tiên.

Hai cuộc gọi trong mã tam giác làm của bạn sẽ không sản xuất đoạn thẳng, trong khi các cuộc gọi tương ứng làm cho squircle sẽ:

addArcToPoint(trianglePath, aroundPoint: cheatPoint, onWayToPoint: bottomCorner, radius: triangleRadius) 
addArcToPoint(trianglePath, aroundPoint: bottomCorner, onWayToPoint: leftCorner, radius: triangleRadius) 

Bạn có thể tự tạo ra các đường nét, tuy nhiên, bằng cách gọi CGPathAddLineToPoint . Và bạn có thể kiểm tra công việc của mình bằng cách sử dụng CGPathApplierFunction, điều này sẽ cho phép bạn liệt kê các điểm kiểm soát.


Cũng ~~~ tôi có thể gợi ý rằng quay một liên kết hiển thị và viết một chức năng mà xác định hình dạng mong muốn cho mỗi t ∈ [0, 1] có lẽ sẽ là một giải pháp dễ bảo trì hơn rõ ràng hơn.

+0

Cảm ơn rất nhiều! Đúng, đây sẽ là một vòng tròn tương tác - bạn kéo nó sang bên trái, vòng tròn trở thành một mũi tên, kéo nó sang bên phải nó đi theo cách khác - vì vậy tôi chắc chắn sẽ cần phải viết chức năng đó! – bryanjclark

+1

Pop framework của Facebook là một cách khá hay để xây dựng hình ảnh động với các đường cong, chuỗi, vv ra khỏi các chức năng như vậy (xem https://github.com/facebook/pop/blob/master/pop/POPAnimatableProperty.h). –

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