2016-03-29 6 views
1

私は画面上に毎秒新しいアニメーションラインを作成しようとしています。 1秒ごとに新しい行が表示されますが、古い行は上書きされます。なぜか分からないのですが、それはおそらく私が見落としているものです。ここに私のコードがある:助けループオーバーライドアニメーションの場合

編集1用

func repeatThis() { 
    for x in 1...10 { 
     let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(x) * Int64(NSEC_PER_SEC)) 
     dispatch_after(time, dispatch_get_main_queue()) { 
      var topLinePatha: UIBezierPath { 
       return UIBezierPath(rect: CGRect(x: 0, y: 0 + (x * 10), width: 1, height: 10)) 
      } 

      var topLinePathb: UIBezierPath { 
       return UIBezierPath(rect: CGRect(x: 0, y: 0 + (x * 10), width: Int(UIScreen.mainScreen().bounds.width), height: 10)) 
      } 

      let expAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path") 
      expAnimation.fromValue = topLinePatha.CGPath 
      expAnimation.toValue = topLinePathb.CGPath 
      expAnimation.duration = self.animationTime 
      expAnimation.fillMode = kCAFillModeForwards 
      expAnimation.removedOnCompletion = false 
      self.addAnimation(expAnimation, forKey: nil) 
      print(x) 
     } 
    } 
} 

ありがとう:

ここで私は基本的にアニメーションがお互いを上書きアニメーションタイミングで抱えている問題です:

func repeatThis() { 
    var runningPath = UIBezierPath() 

    for x in 0...10 { 
     delay(Double(x)/10) { 
      let topLineStartPath = UIBezierPath(rect: CGRect(x: 0, y: x * 10, width: 1, height: 10)) 
      let topLineEndPath = UIBezierPath(rect: CGRect(x: 0, y: x * 10, width: Int(self.bounds.width), height: 10)) 

      let fullStartPath = runningPath.copy() as! UIBezierPath 
      fullStartPath.appendPath(topLineStartPath) 
      let fullEndPath = runningPath.copy() as! UIBezierPath 
      fullEndPath.appendPath(topLineEndPath) 

      let expAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path") 
      expAnimation.fromValue = fullStartPath.CGPath 
      expAnimation.toValue = fullEndPath.CGPath 
      expAnimation.duration = self.animationTime 
      expAnimation.fillMode = kCAFillModeForwards 
      expAnimation.removedOnCompletion = false 
      self.addAnimation(expAnimation, forKey: nil) 
      print(x) 

      runningPath = fullEndPath 
     } 
    } 
} 

func delay(delay:Double, closure:()->()) { 
    dispatch_after(
     dispatch_time(
      DISPATCH_TIME_NOW, 
      Int64(delay * Double(NSEC_PER_SEC)) 
     ), 
     dispatch_get_main_queue(), closure) 
} 
+1

このコードでは「自己」とは何ですか?複数の行を表示するには、そのオブジェクトを複数作成する必要があります。 –

+0

@KurtRevis私は、このようなことをする簡単な方法があるのですか? –

+0

@KurtRevisまた、selfは 'CAShapeLayer'のスーパークラスを持つ' Line'クラスです –

答えて

1

アニメーションを行うたびにコードがCAShapeLayerのパスに置き換わるので、アニメートする各「ライン」に対して過去の行が失われます。複数行を表示するには

、あなたはどちらかの可能性:

  1. は方法UIBezierPath.appendPathを使用して、CAShapeLayerのパスに行ごとに1つずつ、複数のサブパスを追加します。
  2. 各行に1つずつ、CAShapeLayerを複数使用します。

代替コード#1は、現在のコードからの小さな変更です。これは、内蔵のサンプルで、ViewControllerというビューコントローラの新しいiOSプロジェクトに追加できます。

import UIKit 

class MyShapeLayer: CAShapeLayer { 
    var animationTime: NSTimeInterval = 0.75 

    func repeatThis() { 
     // Keep track of the path so far 
     var runningPath = UIBezierPath() 

     for x in 1...10 { 
      let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(x) * Int64(NSEC_PER_SEC)) 
      dispatch_after(time, dispatch_get_main_queue()) { 
       // We will add a rectangular subpath onto runningPath. 
       // It will be animated starting with: 
       let topLineStartPath = UIBezierPath(rect: CGRect(x: 0, y: x * 10, width: 1, height: 10)) 
       // and ending with: 
       let topLineEndPath = UIBezierPath(rect: CGRect(x: 0, y: x * 10, width: Int(self.bounds.width), height: 10)) 

       // Copy the running path, and add the starting and ending subpaths onto it 
       let fullStartPath = runningPath.copy() as! UIBezierPath 
       fullStartPath.appendPath(topLineStartPath) 
       let fullEndPath = runningPath.copy() as! UIBezierPath 
       fullEndPath.appendPath(topLineEndPath) 

       // Animate from fullStartPath to fullEndPath 
       let expAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path") 
       expAnimation.fromValue = fullStartPath.CGPath 
       expAnimation.toValue = fullEndPath.CGPath 
       expAnimation.duration = self.animationTime 
       expAnimation.fillMode = kCAFillModeForwards 
       expAnimation.removedOnCompletion = false 
       self.addAnimation(expAnimation, forKey: nil) 
       print(x) 

       // The next time through the loop, add on to this iteration's ending path 
       runningPath = fullEndPath 
      } 
     } 
    } 
} 

class MyView: UIView { 
    override class func layerClass() -> AnyClass { 
     return MyShapeLayer.self 
    } 
} 

class ViewController: UIViewController { 
    override func loadView() { 
     self.view = MyView() 
     self.view.backgroundColor = UIColor.whiteColor() 
    } 

    override func viewDidLoad() { 
     if let myShapeLayer = self.view.layer as? MyShapeLayer { 
      myShapeLayer.repeatThis() 
     } 
    } 
} 

そして結果:

Animated GIF of the resulting animation

はここで代替#2を実行する方法です。 animationTimeを長くして、各行のアニメーションが重なっていることがわかりました。

class LineAtATimeView: UIView { 
    var animationTime = 1.25 // longer duration so line animations overlap 

    func repeatAddingLines() { 
     for x in 1...10 { 
      let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(x) * Int64(NSEC_PER_SEC)) 
      dispatch_after(time, dispatch_get_main_queue()) { 
       let newLayer = CAShapeLayer() 
       newLayer.frame = self.bounds 
       self.layer.addSublayer(newLayer) 

       let topLineStartPath = UIBezierPath(rect: CGRect(x: 0, y: x * 10, width: 1, height: 10)) 
       let topLineEndPath = UIBezierPath(rect: CGRect(x: 0, y: x * 10, width: Int(self.bounds.width), height: 10)) 

       let expAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path") 
       expAnimation.fromValue = topLineStartPath.CGPath 
       expAnimation.toValue = topLineEndPath.CGPath 
       expAnimation.duration = self.animationTime 
       expAnimation.fillMode = kCAFillModeForwards 
       expAnimation.removedOnCompletion = false 
       newLayer.addAnimation(expAnimation, forKey: nil) 
      } 
     } 
    } 
} 

class ViewController2: UIViewController { 
    override func loadView() { 
     self.view = LineAtATimeView() 
     self.view.backgroundColor = UIColor.whiteColor() 
    } 

    override func viewDidLoad() { 
     if let v = self.view as? LineAtATimeView { 
      v.repeatAddingLines() 
     } 
    } 
} 
+0

申し訳ありませんが、感謝してくれました:)しかし、最初の行が終了する前に新しい行を開始すると、まだアニメーション化されている行が強制終了されます。これを回避する方法はありますか?再度、感謝します。 –

+0

これを行う必要がある場合は、各行に別々の 'CAShapeLayer'を使う方がはるかに簡単です。それから、各行には1つのアニメーションだけが必要であり、それらはすべて独立しているので、それらのアニメーションの一部が同時にアニメーション化されているかどうかは関係ありません。あなたは 'CAShapeLayer'を設定しているコードを表示していないので、私はそれをやろうとしませんでした。 –

+0

各行に独立したレイヤーを作成するためのコードが追加されました。 –