Ios 核心动画-修改动画属性
我有动画Ios 核心动画-修改动画属性,ios,core-animation,Ios,Core 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 rota
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")
}
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
}
我想要的是通过将重复计数设置为1来停止动画,这样它就完成了当前旋转(简单地删除动画是不好的,因为它看起来不好)
我试着跟着
func stopRotate360() {
self.layer.animation(forKey: "rotationAnimation")?.repeatCount = 1
}
但我在控制台里崩溃了
正在尝试修改只读动画
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")
}
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
}
如何访问可写属性?也许这不是最好的解决方案,但它可以工作,正如您所说,一旦创建了
cabasicanition
,您就不能修改属性,我们还需要删除rotation.repeatCount=Float.greatestfinitemagnity,如果不调用
CAAnimationDelegatemethod
animationDidStop',则可以根据需要停止动画,而不会出现任何问题
步骤1:首先声明一个变量标志,以标记您需要在自定义类中停止动画
var needStop : Bool = false
步骤2:在结束后添加停止动画的方法
func stopAnimation()
{
self.needStop = true
}
步骤3:添加一个方法来获取自定义动画
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")
}
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")
}
第5步:在课堂上实施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")
}
}
}
}
这是有效的,并且经过测试
希望这对您有所帮助试试看。事实上,您可以更改正在进行的更改。有很多方法。这是最快/最简单的。您甚至可以完全停止动画并在用户没有注意到的情况下恢复它 您可以看到“开始动画”功能以及“停止”。“开始”动画与您的动画类似,而“停止”从表示层获取当前旋转,并创建一个要旋转直到完成的动画。我还将持续时间平滑为基于当前旋转z完成所需时间的百分比,以基于运行动画的完全旋转。然后,我删除带有重复计数的动画并添加新动画。您可以看到视图平滑地旋转到最终位置并停止。你会明白的。把它放进去运行,看看你的想法。点击按钮开始,然后再次点击,看到它完成旋转并停止
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")
}
}
}
}
结果:2019典型现代语法
按如下方式设置圆弧和图层:
import Foundation
import UIKit
class RoundChaser: UIView {
private let lineThick: CGFloat = 10.0
private let beginFraction: CGFloat = 0.15
// where does the arc drawing begin?
// 0==top, .25==right, .5==bottom, .75==left
private lazy var arcPath: CGPath = {
let b = beginFraction * .pi * 2.0
return UIBezierPath(
arcCenter: bounds.centerOfCGRect(),
radius: bounds.width / 2.0 - lineThick / 2.0,
startAngle: .pi * -0.5 + b,
// recall that .pi * -0.5 is the "top"
endAngle: .pi * 1.5 + b,
clockwise: true
).cgPath
}()
private lazy var arcLayer: CAShapeLayer = {
let l = CAShapeLayer()
l.path = arcPath
l.fillColor = UIColor.clear.cgColor
l.strokeColor = UIColor.purple.cgColor
l.lineWidth = lineThick
l.lineCap = CAShapeLayerLineCap.round
l.strokeStart = 0
l.strokeEnd = 0
// if both are same, it is hidden. initially hidden
layer.addSublayer(l)
return l
}()
那么初始化就这么简单了
open override func layoutSubviews() {
super.layoutSubviews()
arcLayer.frame = bounds
}
最后,动画很简单
public func begin() {
CATransaction.begin()
let e : CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
e.duration = 2.0
e.fromValue = 0
e.toValue = 1.0
// recall 0 will be our beginFraction, see above
e.repeatCount = .greatestFiniteMagnitude
self.arcLayer.add(e, forKey: nil)
CATransaction.commit()
}
}
如果我的回答能解决你的问题,请告诉我question@ReinierMelian我也有同感。哈坎:你能给我们一些关于我们答案的反馈吗?我觉得两个答案都很好,我真的不知道该接受哪一个。我想让读者投票决定吧。