2015-01-09 28 views
0

說下面的場景: 我繪製了一個四邊形形狀,它是UIView的蒙版。我將形狀圖層表示爲maskLayermaskLayer不對稱地裁剪UIView的底部。如何在UIBezierPath中製作兩行以不同速度動畫

但是接下來我想在動畫中充分展示我的UIView。動畫應該是maskLayer的左側下降到UIView的底部,並且.2秒後,我的maskLayer的右側也下降到了UIView的底部,從而充分揭示了UIView的實體。

我的做法是先下拉左線,然後右鍵一個如下面的代碼:

//this quadrilateral will put down left corner to the bottom of screen 
    var path2 = UIBezierPath() 
    path2.moveToPoint(CGPointZero) 
    path2.addLineToPoint(CGPoint(x: 0, y: frame.height)) 
    path2.addLineToPoint(CGPoint(x: frame.width, y: frame.height/goldRatio/goldRatio)) 
    path2.addLineToPoint(CGPoint(x: frame.width, y: 0)) 
    path2.closePath() 

    //this rectangle path will put down both corner to the bottom of screen 
    //thus fix the view to its original shape 
    var path3 = UIBezierPath() 
    path3.moveToPoint(CGPointZero) 
    path3.addLineToPoint(CGPoint(x: 0, y: frame.height)) 
    path3.addLineToPoint(CGPoint(x: frame.width, y: frame.height)) 
    path3.addLineToPoint(CGPoint(x: frame.width, y: 0)) 
    path3.closePath() 

我已經花了2小時試圖弄明白無濟於事。請你給我一些關於如何達到這個目的的指示。

的初始狀態是這樣的: a

的最終狀態是這樣的: b

我真的感謝您的幫助!

回答

0

最簡單的方法來做到這一點...欺騙。

不要嘗試動畫形狀的路徑,它不需要它。

你應該做的是這樣的。

創建您的最終狀態視圖。矩形,在屏幕的底部與UI等等...

此最終狀態視圖不會移動。它將永遠在這裏。

現在創建另一個視圖並將其作爲最終狀態視圖下的子視圖插入。在此,您可以添加一個形狀圖層,並將角形切除。

現在,您只需將該角度視圖的位置向下動畫,直至它完全位於最終狀態視圖的下方。

如果它們具有相同的顏色,則會給出形狀路徑的動畫效果。

爲了獲得不同的速度,您可以將矩形形狀圖層旋轉至45度。然後當視圖滑落時將其動畫到0度?

實際上,您可以使用旋轉和移動的單個形狀圖層進行此操作。

0

要做這種類型的動畫,您通常會使用CADisplayLink(有點像定時器,但鏈接到顯示的更新而不是某些任意間隔)來重複更改與所需形狀相關的path。我認爲這是最簡單的,如果你使用CAShapeLayer,只需更改此形狀的path屬性。

爲了使這項工作,你需要一個代表在給定的時間點的路徑的函數(或者更簡單,在某一時刻某一percentageComplete沿動畫時長的路徑)。既然你有一個規則的形狀(總是相同的點數),你可以簡單地插入一些startPointsendPoints之間的數組。

因此,創建形狀圖層,捕獲開始時間,啓動顯示鏈接,然後爲顯示鏈接的每個「打勾」計算總數爲animationDuration的百分比,並相應地更新形狀圖層的路徑:

class ViewController: UIViewController { 

    let animationDuration = 2.0 
    var displayLink: CADisplayLink! 
    var startTime: CFAbsoluteTime! 
    var shapeLayer: CAShapeLayer! 

    let goldRatio: CGFloat = 1.6180339887 

    var startPoints:[CGPoint]! 
    var endPoints:[CGPoint]! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.startAnimation() 
    } 

    func startAnimation() { 
     startPoints = [ 
      CGPoint(x: 0, y: view.bounds.size.height), 
      CGPoint(x: 0, y: view.bounds.size.height - view.bounds.size.height/goldRatio), 
      CGPoint(x: view.bounds.size.width, y: 0), 
      CGPoint(x: view.bounds.size.width, y: view.bounds.size.height) 
     ] 

     endPoints = [ 
      CGPoint(x: 0, y: view.bounds.size.height), 
      CGPoint(x: 0, y: view.bounds.size.height * 0.75), 
      CGPoint(x: view.bounds.size.width, y: view.bounds.size.height * 0.75), 
      CGPoint(x: view.bounds.size.width, y: view.bounds.size.height) 
     ] 

     assert(startPoints.count == endPoints.count, "Point counts don't match") 

     createShape() 
     startDisplayLink() 
    } 

    func startDisplayLink() { 
     displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:") 
     startTime = CFAbsoluteTimeGetCurrent() 
     displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes) 
    } 

    func stopDisplayLink() { 
     displayLink.invalidate() 
     displayLink = nil 
    } 

    func handleDisplayLink(displayLink: CADisplayLink) { 
     var percent = CGFloat((CFAbsoluteTimeGetCurrent() - startTime)/animationDuration) 

     if percent >= 1.0 { 
      percent = 1.0 
      stopDisplayLink() 
     } 

     updatePathBasedUponPercentComplete(percent) 
    } 

    func createShape() { 
     shapeLayer = CAShapeLayer() 
     shapeLayer.fillColor = UIColor.blueColor().CGColor 
     shapeLayer.strokeColor = UIColor.clearColor().CGColor 
     updatePathBasedUponPercentComplete(0.0) 

     view.layer.addSublayer(shapeLayer) 
    } 

    func updatePathBasedUponPercentComplete(percentComplete: CGFloat) { 
     shapeLayer.path = pathBasedUponPercentComplete(percentComplete, frame: view.frame).CGPath 
    } 

    func pathBasedUponPercentComplete(percentComplete: CGFloat, frame: CGRect) -> UIBezierPath { 
     var path = UIBezierPath() 

     for i in 0 ..< startPoints.count { 
      let point = CGPoint(
       x: startPoints[i].x + (endPoints[i].x - startPoints[i].x) * percentComplete, 
       y: startPoints[i].y + (endPoints[i].y - startPoints[i].y) * percentComplete 
      ) 

      if i == 0 { 
       path.moveToPoint(point) 
      } else { 
       path.addLineToPoint(point) 
      } 
     } 
     path.closePath() 

     return path 
    } 

} 
相關問題