2015-01-09 51 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 
    } 

} 
相关问题