核心animation – 修改animation属性
我有animation
func startRotate360() { let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotation.fromValue = 0 rotation.toValue = Double.pi * 2 rotation.duration = 1 rotation.isCumulative = true rotation.repeatCount = Float.greatestFiniteMagnitude self.layer.add(rotation, forKey: "rotationAnimation") }
我想要的是通过设置其重复次数为1来停止animation的能力,所以它完成当前的旋转(简单地移除animation是不好的,因为它看起来不好)
我尝试跟随
func stopRotate360() { self.layer.animation(forKey: "rotationAnimation")?.repeatCount = 1 }
但是我碰到了,并在控制台
试图修改只读animation
如何访问可写属性?
给一下去。 您实际上可以更改正在进行的CAAnimations。 有很多方法。 这是最快/最简单的。 您甚至可以完全停止animation并在用户不知情的情况下恢复。
您可以看到停止的开始animationfunction。 停止从表示层抓取当前旋转,并创build要旋转的animation,直到完成为止。 根据运行的animation,我还基于当前旋转z到完全旋转,将持续时间平滑为完成所需时间的百分比。 然后我用重复计数删除animation并添加新的animation。 您可以看到视图顺利旋转到最终位置并停止。 你会明白的。 放入并运行它,看看你的想法。 点击button开始,再次点击它看到它完成旋转和停止。
import UIKit class ViewController: UIViewController { var animationView = UIView() var button = UIButton() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. animationView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) animationView.backgroundColor = .green animationView.center = view.center self.view.addSubview(animationView) let label = UILabel(frame: animationView.bounds) label.text = "I Spin" animationView.addSubview(label) button = UIButton(frame: CGRect(x: 20, y: animationView.frame.maxY + 60, width: view.bounds.width - 40, height: 40)) button.setTitle("Animate", for: .normal) button.setTitleColor(.blue, for: .normal) button.addTarget(self, action: #selector(ViewController.pressed), for: .touchUpInside) self.view.addSubview(button) } func pressed(){ if let title = button.titleLabel?.text{ let trans = CATransition() trans.type = "rippleEffect" trans.duration = 0.6 button.layer.add(trans, forKey: nil) switch title { case "Animate": //perform animation button.setTitle("Stop And Finish", for: .normal) rotateAnimationRepeat() break default: //stop and finish button.setTitle("Animate", for: .normal) stopAnimationAndFinish() break } } } func rotateAnimationRepeat(){ //just to be sure because of how i did the project animationView.layer.removeAllAnimations() let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotation.fromValue = 0 rotation.toValue = Double.pi * 2 rotation.duration = 0.5 rotation.repeatCount = Float.greatestFiniteMagnitude //not doing cumlative animationView.layer.add(rotation, forKey: "rotationAnimation") } func stopAnimationAndFinish(){ if let presentation = animationView.layer.presentation(){ if let currentRotation = presentation.value(forKeyPath: "transform.rotation.z") as? CGFloat{ var duration = 0.5 //smooth out duration for change duration = Double((CGFloat(Double.pi * 2) - currentRotation))/(Double.pi * 2) animationView.layer.removeAllAnimations() let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotation.fromValue = currentRotation rotation.toValue = Double.pi * 2 rotation.duration = duration * 0.5 animationView.layer.add(rotation, forKey: "rotationAnimation") } } } }
结果:
也许这不是最好的解决scheme,但它的工作原理,因为你说你不能修改一旦创build的CABasicAnimation
属性,我们还需要删除rotation.repeatCount = Float.greatestFiniteMagnitude, if not
CAAnimationDelegate method
animationDidStop`永远不会被调用,采用这种方法,animation可以在没有任何问题的情况下停下来
第1步:首先声明一个variables标志来标记,因为您需要在自定义类中停止animation
var needStop : Bool = false
第2步:在结束后添加一个stopAnimation方法
func stopAnimation() { self.needStop = true }
第3步:添加一个方法来获取您的自定义animation
func getRotate360Animation() ->CAAnimation{ let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotation.fromValue = 0 rotation.toValue = Double.pi * 2 rotation.duration = 1 rotation.isCumulative = true rotation.isRemovedOnCompletion = false return rotation }
第4步:修改你的startRotate360函数来使用你的getRotate360Animation()
方法
func startRotate360() { let rotationAnimation = self.getRotate360Animation() rotationAnimation.delegate = self self.layer.add(rotationAnimation, forKey: "rotationAnimation") }
第五步:在你的课堂上实现CAAnimationDelegate
extension YOURCLASS : CAAnimationDelegate { func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if(anim == self.layer?.animation(forKey: "rotationAnimation")) { self.layer?.removeAnimation(forKey: "rotationAnimation") if(!self.needStop){ let animation = self.getRotate360Animation() animation.delegate = self self.layer?.add(animation, forKey: "rotationAnimation") } } } }
这工作,并经过testing
希望这可以帮助你
- (Core)animation开始时,图层位置跳转
- iOSanimationUILabel展开
- 在UIView中绘制三angular形切口以供select指示
- 它是如何animationUINavigationBar的条形颜色的变化,而不是一个UITabBar?
- 我如何使通过-addSublayer添加的UI元素:响应触摸事件?
- 如何以编程方式快速发送pangesture
- 什么是创build圆圈animation的正确方法?
- UITableView中的错误(deleteSections:withRowAnimation:)?
- iOS 10 UILabels – > 1 UIView – >通过animation循环