CAShapeLayer上的CABasicAnimation无法用于路径更改 [英] CABasicAnimation on CAShapeLayer not working for path change
问题描述
我有一个进度方法此处:
func progress(incremented : CGFloat){
if incremented <= self.bounds.width{
self.progressLayer.removeFromSuperlayer()
let originBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:0, height:self.bounds.height) , cornerRadius: self.viewCornerRadius)
originBezierPathProg.close()
let newBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:incremented, height:self.bounds.height) , cornerRadius: self.viewCornerRadius)
bezierPathProg.close()
self.progressLayer.path = originBezierPathProg.cgPath
self.borderLayer.addSublayer(self.progressLayer)
let animation = CABasicAnimation(keyPath: "path")
animation.fromValue = originBezierPathProg.cgPath
animation.toValue = newBezierPathProg.cgPath
animation.duration = 1
self.progressLayer.add(animation, forKey: animation.keyPath)
self.progressLayer.path = newBezierPathProg.cgPath
}
}
我正在尝试制作进度条以动画方式显示进度。但是当我调用 progress(100)
时,它只是在没有动画的情况下渲染了条形图。
I am trying to make progress bar progress in an animated way. But when I call progress(100)
, it's simply rendering the bar without animation.
如何修复它?
更新:根据Rob的建议创建了MCVE: https://github.com/utkarsh2012/ProgressBarTest 。我希望进度条从width = 0到width = x进行动画处理(例如60)
Update: Created MCVE as per Rob's suggestion: https://github.com/utkarsh2012/ProgressBarTest . I expect the progress bar to animate from width=0 to width=x (say 60)
看起来类似于此问题使用CALayer路径的CABasicAnimation无法设置动画
推荐答案
问题中最初显示的进度
方法很好。问题在于您如何使用它。话虽如此,让我们看一下MCVE。
The progress
method originally shown in your question is fine. The problem is in how you used it. That having been said, let's go through the MCVE.
在您的MCVE ,有一些阻止动画的内容,即:
In your MCVE, there were a few things preventing the animation, namely:
-
progress
方法如下:
func progress(incremented: CGFloat) {
if incremented <= bounds.width {
let toPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: incremented + 100, height: bounds.height), cornerRadius: viewCornerRadius)
progressLayer.path = toPath.cgPath
borderLayer.addSublayer(progressLayer)
let animation = CABasicAnimation(keyPath: "path")
animation.fromValue = self.progressLayer.path
animation.toValue = toPath.cgPath
animation.duration = 3
progressLayer.add(animation, forKey: animation.keyPath)
}
}
这是将路径
设置为新路径,然后从该路径动画到新路径(即动画与同一路径之间的动画)。因此,没有动画。
That is setting the path
to be the new path, and then animating from that to the new path (i.e. animating to and from the same path). Thus, no animation.
在将路径
更改为其新的结束状态并启动动画之前,请保存旧路径。将保存的路径用作动画的 fromValue
。
Save the old path before changing the path
to its new "end state" and initiating the animation. Use that saved path as the fromValue
of the animation.
值
属性正在调用 layoutSubviews
:
var value: Int? {
didSet {
progress(value: value!)
self.layoutSubviews()
}
}
从不直接调用 layoutSubviews()
。
视图控制器正在执行以下操作:
The view controller was doing the following:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let view = DetailView(frame: self.view.frame)
view.value = 60
self.containerView.addSubview(view)
}
不要尝试在 viewDidLoad
中启动动画。在视图生命周期中还为时过早。改用 viewDidAppear
(或其他)。在 viewDidLoad
中执行此操作通常在视图生命周期中为时过早。
Don't try to start animations in viewDidLoad
. That's too early in the view lifecycle. Use viewDidAppear
(or whatever) instead. Doing this in viewDidLoad
is generally too early in the view lifecycle.
与该<$ c有关$ c> viewDidLoad 代码,您正在更改 DetailView
的值
(已触发动画)),然后再将其添加到视图层次结构中。
Related to that viewDidLoad
code, you were changing the value
of the DetailView
(which triggered the animation) before you've added it to the view hierarchy.
在此处查看修复程序 https://github.com/robertmryan/ProgressBarTest 。
这篇关于CAShapeLayer上的CABasicAnimation无法用于路径更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!