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,每行一个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中的代码在所有情况下都应该有效。如果没有,请使用代码询问另一个问题,以重现问题所在的确切问题。