2017-07-31 189 views
2

我申请了CAShapeLayer(让我们将其命名为pulseLayer)2个动画,使用此代码:如何更新CABasicAnimation的toValue/fromValue更改时更平滑?

let scaledAnimation = CABasicAnimation(keyPath: "transform.scale.xy") 
scaledAnimation.duration  = 0.75 
scaledAnimation.repeatCount = Float.infinity 
scaledAnimation.autoreverses = true 
scaledAnimation.fromValue  = 4 
scaledAnimation.toValue  = 4 
scaledAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 

let heartBeatAnimation = CABasicAnimation(keyPath: "transform.scale.xy") 
heartBeatAnimation.duration  = 0.75 
heartBeatAnimation.repeatCount = Float.infinity 
heartBeatAnimation.autoreverses = true 
heartBeatAnimation.fromValue  = 1.0 
heartBeatAnimation.toValue  = 1.2 
heartBeatAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 

pulseLayer.add(heartBeatAnimation, forKey: "heartBeatAnimation") 

在某些时候,而heartBeatAnimation是我需要删除心脏跳动的动画,并用这个代码添加的缩放动画:

pulseLayer.add(self.scaledAnimation, forKey: "scaledAnimation") 
pulseLayer.opacity = 0.55 
pulseLayer.removeAnimation(forKey: "heartBeatAnimation") 

,但我没有得到这两动画之间的平滑过渡,即使UIView.animate()

,所以我努力让自己只有一个动画heartBeatAnimation并改变其toValuefromValue相同的值,以获得尽可能scaledAnimation与此代码:

而动画后消失,用户做了一些手势,开始我拿到了动画的动画跳动
heartBeatAnimation.toValue = 4 
heartBeatAnimation.fromValue = 4 

什么都没有发生缩放稳定动画...!

所以任何想法如何更新这些值,使缩放的动画更平滑!

+0

我认为你需要设置heartBeatAnimation.toValue = 4,heartBeatAnimation.fromValue = 0,为平稳过渡 – Hitesh

回答

1

试试看看。完整的动画两者之间的切换是取决于CABasicAnimation的 duration, count, fromValue and toValue性能与UIView.animate关闭

@IBOutlet var vwAnimation: UIView! 
    let initialScale: CGFloat = 1.0 
    let animatingScale: CGFloat = 2.0 
    let finalScale: CGFloat = 3.0 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     addAnimation() 
    } 


    func addAnimation(){ 

     heartBeatAnimation() 
     self.perform(#selector(self.switchAnimation), with: nil, afterDelay: 3.0) 
    } 

    @objc func switchAnimation(){ 

     UIView.animate(withDuration: 0.25, animations: { 
      self.vwAnimation.layer.removeAnimation(forKey: "heartBeatAnimation") 
      self.scaledAnimation() 
      self.vwAnimation.layoutIfNeeded() 
     }) { (isCompleted) in 

     } 
    } 


    func scaledAnimation() -> Void { 

     let scaledAnimation = CABasicAnimation(keyPath: "transform.scale.xy") 
     scaledAnimation.duration  = 0.5 
     scaledAnimation.repeatCount = 0.5 
     scaledAnimation.autoreverses = true 
     scaledAnimation.fromValue  = initialScale 
     scaledAnimation.toValue  = finalScale 
     scaledAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 
     vwAnimation.layer.add(scaledAnimation, forKey: "scaledAnimation") 

     self.perform(#selector(self.adjustScale), with: nil, afterDelay: 0.5) 
    } 

    @objc func adjustScale(){ 
     self.vwAnimation.layer.removeAnimation(forKey: "scaledAnimation") 
     let scaleTransform = CGAffineTransform(scaleX: finalScale, y: finalScale) 
     vwAnimation.transform = scaleTransform 
    } 


    func heartBeatAnimation() -> Void { 

     let heartBeatAnimation = CABasicAnimation(keyPath: "transform.scale.xy") 
     heartBeatAnimation.duration  = 0.5 
     heartBeatAnimation.repeatCount = Float.infinity 
     heartBeatAnimation.autoreverses = true 
     heartBeatAnimation.fromValue  = initialScale 
     heartBeatAnimation.toValue  = animatingScale 
     heartBeatAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 
     vwAnimation.layer.add(heartBeatAnimation, forKey: "heartBeatAnimation") 

    } 

这里是上面代码的结果,并让我知道如果想在这个结果的变化:

enter image description here

+0

我要缩放并保持只是一个眨眼不进行缩放! –

+0

我的意思是我想保持缩放。 –

+0

Yaa,它在动画结束时缩放为'3x(scaleOfView = 3.0)',你可以在这里看到 – Krunal

0

不使用延迟等,并使用CATransaction和CASpringAnimations。

import UIKit 

class ViewController: UIViewController { 

    var shapeLayer : CAShapeLayer! 
    var button : UIButton! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     //add a shapelayer 
     shapeLayer = CAShapeLayer() 
     shapeLayer.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width/4, height: self.view.bounds.width/4) 
     shapeLayer.position = self.view.center 
     shapeLayer.path = drawStarPath(frame: shapeLayer.bounds).cgPath 
     let color = UIColor(red: 0.989, green: 1.000, blue: 0.000, alpha: 1.000) 
     shapeLayer.fillColor = color.cgColor 
     self.view.layer.addSublayer(shapeLayer) 


     //button for action 
     button = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width - 20, height: 50)) 
     button.center = self.view.center 
     button.center.y = self.view.bounds.height - 70 
     button.addTarget(self, action: #selector(ViewController.pressed(sender:)), for: .touchUpInside) 
     button.setTitle("Animate", for: .normal) 
     button.setTitleColor(.blue, for: .normal) 

     self.view.addSubview(button) 

    } 

    func pressed(sender:UIButton) { 

     if button.titleLabel?.text == "Reset Layer"{ 
      reset() 
      return 
     } 


     //perform Animation 
     button.isEnabled = false 
     button.setTitle("Animating...", for: .normal) 

     let heartBeatAnimation = CABasicAnimation(keyPath: "transform.scale.xy") 
     heartBeatAnimation.duration  = 0.5 
     heartBeatAnimation.repeatCount = 2 
     heartBeatAnimation.autoreverses = true 
     heartBeatAnimation.fromValue  = 1.0 
     heartBeatAnimation.toValue  = 2.0 
     heartBeatAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     CATransaction.begin() 
     CATransaction.setCompletionBlock { 
      //call when finished 
      [weak self] in 
      if let vc = self{ 
       vc.scaleUpToComplete() 
      } 

     } 
     shapeLayer.add(heartBeatAnimation, forKey: "beatAnimation") 
     CATransaction.commit() 
    } 

    func scaleUpToComplete(){ 

     let scaledAnimation = CASpringAnimation(keyPath: "transform.scale.xy") 
     scaledAnimation.duration  = 0.7 
     scaledAnimation.fromValue  = 1.0 
     scaledAnimation.toValue  = 2.0 
     scaledAnimation.damping = 8.0 
     scaledAnimation.initialVelocity = 9 
     scaledAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     CATransaction.begin() 
     CATransaction.setCompletionBlock { 
      //set transform 
      [weak self] in 
      if let vc = self{ 
       let scaleTransform = CATransform3DScale(CATransform3DIdentity, 2.0, 2.0, 1) 
       vc.shapeLayer.transform = scaleTransform 
       vc.shapeLayer.removeAllAnimations() 

       //button title and enabled 
       vc.button.isEnabled = true 
       vc.button.setTitle("Reset Layer", for: .normal) 

      } 
     } 
     shapeLayer.add(scaledAnimation, forKey: "scaleUp") 
     CATransaction.commit() 
    } 


    func reset(){ 
     let scaledAnimation = CASpringAnimation(keyPath: "transform.scale.xy") 
     scaledAnimation.duration  = 0.7 
     scaledAnimation.fromValue  = 2.0 
     scaledAnimation.toValue  = 1.0 
     scaledAnimation.damping = 8.0 
     scaledAnimation.initialVelocity = 9 
     scaledAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     CATransaction.begin() 
     CATransaction.setCompletionBlock { 
      //set transform 
      [weak self] in 
      if let vc = self{ 
       let scaleTransform = CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 1) 
       vc.shapeLayer.transform = scaleTransform 
       vc.shapeLayer.removeAllAnimations() 
       vc.button.setTitle("Animate", for: .normal) 
      } 
     } 
     shapeLayer.add(scaledAnimation, forKey: "scaleDown") 
     CATransaction.commit() 

    } 

    func drawStarPath(frame: CGRect = CGRect(x: 0, y: 0, width: 140, height: 140)) ->UIBezierPath{ 
     //// Star Drawing 
     let starPath = UIBezierPath() 
     starPath.move(to: CGPoint(x: frame.minX + 0.50000 * frame.width, y: frame.minY + 0.21071 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.60202 * frame.width, y: frame.minY + 0.35958 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.77513 * frame.width, y: frame.minY + 0.41061 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.66508 * frame.width, y: frame.minY + 0.55364 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.67004 * frame.width, y: frame.minY + 0.73404 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.50000 * frame.width, y: frame.minY + 0.67357 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.32996 * frame.width, y: frame.minY + 0.73404 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.33492 * frame.width, y: frame.minY + 0.55364 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.22487 * frame.width, y: frame.minY + 0.41061 * frame.height)) 
     starPath.addLine(to: CGPoint(x: frame.minX + 0.39798 * frame.width, y: frame.minY + 0.35958 * frame.height)) 
     return starPath 
    } 
}