Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 用于循环覆盖动画_Swift_Core Animation - Fatal编程技术网

Swift 用于循环覆盖动画

Swift 用于循环覆盖动画,swift,core-animation,Swift,Core Animation,我试图在屏幕上每秒创建一条新的动画线条。每一秒我都会得到一条新的线路,但是它会覆盖旧的线路。我不知道为什么,但我可能忽略了一些愚蠢的事情。这是我的密码: 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, d

我试图在屏幕上每秒创建一条新的动画线条。每一秒我都会得到一条新的线路,但是它会覆盖旧的线路。我不知道为什么,但我可能忽略了一些愚蠢的事情。这是我的密码:

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)
        }
    }
}
谢谢你的帮助

编辑1:

这里有一个关于动画计时的问题,动画基本上是相互覆盖的:

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)
}

每次制作动画时,您的代码都会替换
CAShapeLayer
的路径,因此对于在其中制作动画的每一行,您都会丢失过去的行

要显示多行,您可以:

  • 使用以下方法将多个子路径添加到
    CAShapeLayer
    的路径中,每行一个子路径
  • 使用多个
    CAShapeLayer
    s,每行一个
  • 这里是备选方案#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()
            }
        }
    }
    
    结果是:

    这里有一种方法可以做备选方案2。我延长了动画时间,以便您可以看到每条线的动画可以重叠

    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()
            }
        }
    }
    

    此代码中的
    self
    是什么?如果你想显示多行,你必须制作多行。@KurtRevis我的意思是,有没有更简单的方法来做这样的事情?@KurtRevis也是self的一个类
    line
    ,它有一个超类
    CAShapeLayer
    ,好的,谢谢:)。但是,当我在第一行完成之前开始一个新行时,它会强制仍在设置动画的行完成。有办法解决这个问题吗?再次感谢。如果您需要这样做,那么为每行使用单独的
    CAShapeLayer
    会容易得多。然后每一行只需要一个动画,并且它们都是独立的,所以如果其中一些动画同时进行,这并不重要。您没有显示设置
    CAShapeLayer
    的代码,因此我没有尝试这样做。添加代码为每行创建一个独立的层。嘿,感谢更新。我想你误解了这个问题,对不起!我遇到的问题是
    dispatch\u time
    的位置是我将它设置为一个小得多的数字。。。比如说0.25,当它运行时,每次我开始一条新的线路,它都会跳过在它结束之前的那个线路。这有意义吗?有两个不同的时间:(1)动画持续时间
    self.animationTime
    ,和(2)每次循环后分配给
    dispatch\u的时间差。您对每一项的具体价值是什么?我认为备选方案2中的代码在所有情况下都应该有效。如果没有,请使用代码询问另一个问题,以重现问题所在的确切问题。