Ios 使用CAShapeLayer对圆进行多次动画制作
当用户点击一个按钮时,我需要设置一个圆圈的进度动画。我目前正在使用Ios 使用CAShapeLayer对圆进行多次动画制作,ios,swift,cashapelayer,Ios,Swift,Cashapelayer,当用户点击一个按钮时,我需要设置一个圆圈的进度动画。我目前正在使用CAShapeLayer和CABasicAnimation。代码如下: import UIKit class ViewController: UIViewController { @IBOutlet weak var circleContainerView: UIView! var progressPts = [0.1, 0.3, 0.7, 0.5] let circleLayer = CAShap
CAShapeLayer
和CABasicAnimation
。代码如下:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var circleContainerView: UIView!
var progressPts = [0.1, 0.3, 0.7, 0.5]
let circleLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
setupCircle()
}
@IBAction func didTapAnimate(_ sender: Any) {
guard let pt = progressPts.first else { return }
let animateStroke = CABasicAnimation(keyPath: "strokeEnd")
animateStroke.toValue = pt
animateStroke.duration = 2.0
animateStroke.fillMode = .forwards
animateStroke.isRemovedOnCompletion = false
circleLayer.add(animateStroke, forKey: "MyAnimation")
progressPts.removeFirst()
}
private func setupCircle() {
circleLayer.frame = CGRect(origin: .zero, size: circleContainerView.bounds.size)
let center = CGPoint(x: circleLayer.bounds.width / 2.0,
y: circleLayer.bounds.height / 2.0)
circleLayer.path = UIBezierPath(arcCenter: center,
radius: (circleLayer.bounds.height / 2.0) - 5.0,
startAngle: 0,
endAngle: 2 * CGFloat.pi, clockwise: true).cgPath
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineWidth = 10.0
circleLayer.strokeColor = UIColor.red.cgColor
circleLayer.strokeEnd = 0.0
circleContainerView.layer.addSublayer(circleLayer)
}
}
为了在动画结束时笔划保持在正确的位置,我需要将填充模式也设置为。向前
和isRemovedOnCompletion
设置为false
。这适用于第一个动画。但是,在下一个动画中,斯托克首先重置:
我做错了什么?如何在不重置的情况下为每个新的进度位置设置动画?另外,将isRemovedOnCompletion
设置为false
当然是一个坏主意,因为该层最终将附加多个动画。我刚刚使用了“从值”属性来完成循环,而没有重置,它将平滑地设置动画,只需使用下面的代码即可
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var circleContainerView: UIView!
var progressPts = [0.1, 0.3, 0.7, 0.5]
var previousPts = 0.0
let circleLayer = CAShapeLayer()
var animateStroke: CABasicAnimation!
override func viewDidLoad() {
super.viewDidLoad()
setupCircle()
}
@IBAction func didTapAnimate(_ sender: Any) {
guard let pt = progressPts.first else { return }
animateStroke.fromValue = previousPts
animateStroke.toValue = pt
animateStroke.duration = 2.0
animateStroke.fillMode = .forwards
animateStroke.isRemovedOnCompletion = false
circleLayer.add(animateStroke, forKey: "MyAnimation")
previousPts = progressPts.removeFirst()
}
private func setupCircle() {
animateStroke = CABasicAnimation(keyPath: "strokeEnd")
circleLayer.frame = CGRect(origin: .zero, size: circleContainerView.bounds.size)
let center = CGPoint(x: circleLayer.bounds.width / 2.0,
y: circleLayer.bounds.height / 2.0)
circleLayer.path = UIBezierPath(arcCenter: center,
radius: (circleLayer.bounds.height / 2.0) - 5.0,
startAngle: 0,
endAngle: 2 * CGFloat.pi, clockwise: true).cgPath
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineWidth = 10.0
circleLayer.strokeColor = UIColor.red.cgColor
circleLayer.strokeEnd = 0.0
circleContainerView.layer.addSublayer(circleLayer)
}
}
输出
希望以下解决方案对您有效。您应用了以下解决方案吗?谢谢。我忘了从value更改。但是,使用此解决方案,每次都会向层添加一个新动画。因为isRemovedOnCompletion
设置为false
。这不会对性能产生负面影响吗?您可以通过在setupCircle方法内部初始化animateStroke
来优化代码,这样它将只初始化一次,并且只更新值(请参阅更新的代码)。我认为这不会影响性能。