我想在從一個圓轉換爲圓角三角形時創建一個形狀的動畫。將一個CAShapeLayer圓動畫成一個圓角三角形
TL; DR:如何在兩個CGPath
形狀之間創建CAShapeLayer
的path
動畫?我知道他們需要有相同數量的控制點,但我認爲我正在這麼做 - 這段代碼有什麼問題?
的開始和結束時的狀態會是這個樣子: transition http://clrk.it/4vJS+
這裏是我試過到目前爲止:我使用的是CAShapeLayer
,和動畫在其path
屬性的變化。
按照documentation(重點煤礦):
的路徑對象可以使用任何
CAPropertyAnimation
的具體子類的動畫。路徑將作爲「在線」點的線性混合插值; 「離線」點可以非線性地內插(例如,以保持曲線導數的連續性)。 如果兩個路徑具有不同數量的控制點或分段,則結果未定義。
在試圖得到圓形和三角形有相同數量的控制點,我讓他們都四角形狀:圓是一個重圓角矩形,三角形被「隱藏」一邊是第四個控制點。
這裏是我的代碼:
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
...,後來,在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")
我有兩個小巧的功能使代碼更易讀:
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)
}
我目前的結果是這樣的:
注:我試圖打造出圓一個非常全面的廣場,企圖得到的矢量形狀相同數量的控制點。在上面的GIF中,拐角半徑已經減小,以使變形更明顯。
你認爲怎麼回事?我可以怎樣才能達到這個效果?
嘗試使用很多直線段代替兩種形狀? – nielsbot
實際上,你確定你正在使用addArcToPoint()嗎? – nielsbot
(我不叮囑*路徑*參數addArcToPoint()是可選的) – nielsbot