Swift 3 动画问题

Posted

技术标签:

【中文标题】Swift 3 动画问题【英文标题】:Swift 3 animation issue 【发布时间】:2016-10-28 23:29:54 【问题描述】:

我正在实现简单地为颜色设置动画的进度视图。

除了按形状填充并使其闪烁的“strokeEnd”动画之外,一切都运行良好。

视频resource

代码示例:

class MaterialCircularProgressView: UIView 

    let circularLayer = CAShapeLayer()
    let googleColors = [
        UIColor(red:0.282, green:0.522, blue:0.929, alpha:1),
        UIColor(red:0.859, green:0.196, blue:0.212, alpha:1),
        UIColor(red:0.957, green:0.761, blue:0.051, alpha:1),
        UIColor(red:0.235, green:0.729, blue:0.329, alpha:1)
    ]

    let inAnimation: CAAnimation = 
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = 0.0
        animation.toValue = 1.0
        animation.duration = 1.0
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

        return animation
    ()

    let outAnimation: CAAnimation = 
        let animation = CABasicAnimation(keyPath: "strokeStart")
        animation.beginTime = 0.5
        animation.fromValue = 0.0
        animation.toValue = 1.0
        animation.duration = 1.0
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

        return animation
    ()

    let rotationAnimation: CAAnimation = 
        let animation = CABasicAnimation(keyPath: "transform.rotation.z")
        animation.fromValue = 0.0
        animation.toValue = 2 * M_PI
        animation.duration = 2.0
        animation.repeatCount = MAXFLOAT

        return animation
    ()

    var colorIndex : Int = 0

    override init(frame: CGRect) 
        super.init(frame: frame)

        circularLayer.lineWidth = 4.0
        circularLayer.fillColor = nil
        layer.addSublayer(circularLayer)
    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    override func layoutSubviews() 
        super.layoutSubviews()

        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        let radius = min(bounds.width, bounds.height) / 2 - circularLayer.lineWidth / 2

        let arcPath = UIBezierPath(arcCenter: CGPoint.zero, radius: radius, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI_2 + (2 * M_PI)), clockwise: true)

        circularLayer.position = center
        circularLayer.path = arcPath.cgPath

        animateProgressView()
        circularLayer.add(rotationAnimation, forKey: "rotateAnimation")
    


    func animateProgressView() 

        circularLayer.removeAnimation(forKey: "strokeAnimation")

        circularLayer.strokeColor = googleColors[colorIndex].cgColor

        let strokeAnimationGroup = CAAnimationGroup()
        strokeAnimationGroup.duration = 1.0 + outAnimation.beginTime
        strokeAnimationGroup.repeatCount = 1
        strokeAnimationGroup.animations = [inAnimation, outAnimation]
        strokeAnimationGroup.delegate = self

        circularLayer.add(strokeAnimationGroup, forKey: "strokeAnimation")

        colorIndex += 1;
        colorIndex = colorIndex % googleColors.count;
    



extension MaterialCircularProgressView: CAAnimationDelegate

    override func animationDidStop(_ anim: CAAnimation, finished flag: Bool) 
        if(flag) 
            animateProgressView()
        
    


【问题讨论】:

【参考方案1】:

您可以通过在初始化程序中将 strokeStart 设置为 outAnimation 的最终值来解决闪烁问题:

circularLayer.strokeStart = 1.0

原因是CAPropertyAnimation 动画属性的实际值不会自动设置为动画的toValue,因此它会恢复为原始值,在您的情况下为0.0。这就是为什么会出现一段时间的完整圆圈。

但是在下一个圆圈出现之前会有延迟,不确定这是您的意图还是要修复的其他错误。

【讨论】:

以上是关于Swift 3 动画问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用swift 3为按钮设置动画以淡出然后淡入

Swift 3 iOS 10 - 将“滑动解锁”动画应用于标签

动画委托未转换为 Swift 3.0

UIButtons 在动画期间没有响应 - iOS Swift 3

无法在 Swift 中使用时间延迟为 UIImage 设置动画

在 swift iOS 中为 3 个点设置动画