具有重复和延迟的animateKeyframes无法按预期工作

时间:2017-02-28 19:37:09

标签: ios animation swift3

我正在使用关键帧为标签创建一个简单的从左到右的动画,但是当动画重复时,会忽略延迟。

第一次执行时,3秒的延迟有效,但是当动画重复时,忽略延迟。这会导致动画在结束后立即重新启动。

UIView.animateKeyframes(withDuration: 10, delay: 3, options: [.calculationModePaced, .repeat], animations: {
    let xDist = self.Label_ArtistAlbum2.frame.origin.x

    UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.1, animations: {
        self.Label_ArtistAlbum2.frame.origin.x = self.Label_ArtistAlbum2.frame.origin.x - (xDist * 0.1)
    })

    UIView.addKeyframe(withRelativeStartTime: 0.9, relativeDuration: 0.1, animations: {
        self.Label_ArtistAlbum2.frame.origin.x = 0
    })
}, completion: nil)

我已经尝试在最后添加一个额外的关键帧,但即使更改时间也没有效果:

UIView.animateKeyframes(withDuration: 10, delay: 3, options: [.calculationModePaced, .repeat], animations: {
    let xDist = self.Label_ArtistAlbum2.frame.origin.x

    UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.1, animations: {
        self.Label_ArtistAlbum2.frame.origin.x = self.Label_ArtistAlbum2.frame.origin.x - (xDist * 0.1)
    })

    UIView.addKeyframe(withRelativeStartTime: 0.1, relativeDuration: 0.7, animations: {
        self.Label_ArtistAlbum2.frame.origin.x = 0
    })

    //attempted pause - does not appear to work perhaps since the position is unchanged?
    UIView.addKeyframe(withRelativeStartTime: 0.8, relativeDuration: 0.2, animations: {
        self.Label_ArtistAlbum2.frame.origin.x = 0
    })
}, completion: nil)

如果延迟不会与动画的其余部分一起重复,如何在整个动画重复之前创建暂停?

2 个答案:

答案 0 :(得分:1)

我已经在这个问题上做了很多测试,并找到了我认为的问题。

我认为曲线的动画选项是我的问题。 在我的情况下选择

<强> calculationModePaced

具有重新计算我的关键帧参数的效果,并且不保证除了开头和结尾之外都会击中它们中的任何一个。所有中间关键帧都成为“建议”。 你不能在最后创建一个暂停,因为关键帧在重新计算时被“消耗”,并且不能独立存在。

我改为calculateModeLinear并获得了我期望的关键帧,以及暂停。 但是,它和我想的一样顺畅,所以我不得不继续修补......

Apple的文档在这里 - 它们是描述性的,但可以真正使用一些图形和/或示例: https://developer.apple.com/reference/uikit/uiview?language=swift

可在此处找到曲线的良好图表:https://www.shinobicontrols.com/blog/ios7-day-by-day-day-11-uiview-key-frame-animations

答案 1 :(得分:0)

我在为加载视图设置动画方面遇到了类似的问题。我这样解决了:

我为动画中的步骤创建了一个枚举

private enum TriangleToAnimate {
    case one
    case two
    case three
    case pause
}

我有我的变量

private var triangleViewToFireCount = TriangleToAnimate.one
var triangle1View : TriangleView
var triangle2View : TriangleView
var triangle3View : TriangleView

我启动一个计时器来运行每个动画

override init(frame: CGRect) {
    Timer.scheduledTimer(timeInterval: 0.33, target: self, selector: #selector(LoadingView.timerFire), userInfo: nil, repeats: true)
}

对于选择器我有一个火法。在方法中,我为每个枚举案件设置了一个开关

func timerFire(){
    let anim = createAnimation()
    switch triangleViewToFireCount {
    case .one:
        triangle1View.layer.add(anim, forKey: "transform")
        triangleViewToFireCount = .two
    case .two:
        triangle2View.layer.add(anim, forKey: "transform")
        triangleViewToFireCount = .three
    case .three:
        triangle3View.layer.add(anim, forKey: "transform")
        triangleViewToFireCount = .pause
    default:
        triangleViewToFireCount = .one
    }
}

这是我将动画创建为关键帧的代码

func createAnimation() -> CAKeyframeAnimation{
    let tr = CATransform3DIdentity
    let orignalScale = CATransform3DScale(tr, 1, 1, 1)
    let doubleScale = CATransform3DScale(tr, 2, 2, 1)
    let keyAn = CAKeyframeAnimation(keyPath: "transform")
    keyAn.keyTimes = [0, 0.1, 0.6]
    keyAn.duration = 1
    keyAn.values = [orignalScale,doubleScale,orignalScale]
    keyAn.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
    return keyAn
}