当 CAAnimationGroup 的执行完成时,它会回到初始动画序列,并带有抽搐效果
Posted
技术标签:
【中文标题】当 CAAnimationGroup 的执行完成时,它会回到初始动画序列,并带有抽搐效果【英文标题】:When CAAnimationGroup's execution is completed, it goes back to initial animation sequence with a jerking effect 【发布时间】:2020-08-08 08:57:11 【问题描述】:在这里,我正在创建一个消失的圆形图层动画。我的代码如下:
import UIKit
class VanishingLoader: UIView
private let loaderLayer = CAShapeLayer()
private var layerPaths = [UIBezierPath]()
private let animationframeDuration = 0.25
private var lastFrameDuration = 0.0
weak var parentView: UIView?
var parenViewCenter: CGPoint?
if let frame = parentView?.bounds
return CGPoint(x: frame.midX, y: frame.midY)
return nil
let animationGroup = CAAnimationGroup()
required init?(coder: NSCoder)
super.init(coder: coder)
init(onView view: UIView)
super.init(frame: view.frame)
parentView = view
layerPaths = preparedPathList
if layerPaths.count > 0
let path = layerPaths[0]
addVanishingStrokeLayer(path, withStrokeColor: UIColor.systemGreen, andStrokeWidth: nil)
private func addVanishingStrokeLayer(_ path: UIBezierPath, withStrokeColor strokeColor:UIColor?, andStrokeWidth strokeWidth: CGFloat?)
let initialPath = layerPaths[0].cgPath
loaderLayer.path = initialPath
loaderLayer.fillColor = UIColor.clear.cgColor
if let loaderLayerColor = strokeColor
loaderLayer.strokeColor = loaderLayerColor.cgColor
else
loaderLayer.strokeColor = defaultStrokeColor.cgColor
if let lineWidth = strokeWidth
loaderLayer.lineWidth = lineWidth
else
loaderLayer.lineWidth = 5.0
loaderLayer.add(vanishingAnimationGroup(), forKey: "vanishingGroupAnimation")
self.layer.addSublayer(loaderLayer)
var preparedPathList: [UIBezierPath]
var pathList = [UIBezierPath]()
var multiplier : CGFloat = 0.3
for _ in 0..<8
if let path = getPathForLayer(withMultiplier: multiplier)
pathList.append(path)
multiplier += 0.10
return pathList
private func getPathForLayer(withMultiplier multiplier: CGFloat = 1.0)->UIBezierPath?
let radius = 5.0
let path = UIBezierPath(arcCenter: .zero , radius: radius, startAngle: 0, endAngle: 4 * CGFloat.pi, clockwise: true)
return path
private func prepareForwardAnimationFrame(forPathCount count: Int)->CASpringAnimation
let initialPath = layerPaths[count]
let finalPath = layerPaths[count + 1]
let pathAnimation = CASpringAnimation(keyPath: "path")
pathAnimation.fromValue = initialPath.cgPath
pathAnimation.toValue = finalPath.cgPath
pathAnimation.initialVelocity = 1
pathAnimation.damping = 5
pathAnimation.beginTime = lastFrameDuration
pathAnimation.duration = animationframeDuration
return pathAnimation
private func vanishingAnimationGroup()->CAAnimationGroup
var animationPaths = [CASpringAnimation]()
for count in 0..<(layerPaths.count - 1)
let anim = prepareForwardAnimationFrame(forPathCount: count)
animationPaths.append(anim)
lastFrameDuration = anim.beginTime + animationframeDuration
animationGroup.animations = animationPaths
animationGroup.duration = (Double(animationPaths.count) * animationframeDuration)
animationGroup.repeatCount = .infinity
animationGroup.fillMode = .forwards
animationGroup.isRemovedOnCompletion = false
return animationGroup
public func hide()
self.removeFromSuperview()
public func show()
if let view = parentView
view.addSubview(self)
从 ViewController 中,必须添加以下两行才能看到效果。
let loader = VanishingLoader(onView: placeHolderImageView)
loader.show()
我面临的问题是,当动画序列结束时,它会回到初始路径,这是七条路径中最小的一条,并且会产生突然的抽搐效果。请帮帮我。
【问题讨论】:
【参考方案1】:首先,这应该是关键帧动画,而不是分组动画。其次,从 last 到 first 的变化没有动画,因为 you 没有动画。添加另一个执行缺失动画的关键帧。
我把你的动画改写成关键帧动画了,到现在也有这个,但是我觉得不是你想要的,所以请说清楚应该是什么效果:
【讨论】:
你能提供一些代码吗?我已经根据您的建议更新了我的代码,但它根本不起作用。现在它甚至没有动画。请查看我更新的帖子。 因为这不是您制作关键帧动画的方式。关键时间是分数。 我添加了 keyTimes 数组,其中包含我希望每个关键帧的持续时间的分数。依然没有。用你的建议更新了我的答案.. 为了突出重点,我发布了主要部分。由于您还不够清楚,我正在用整个自定义类更新我的问题。 让我们continue this discussion in chat。以上是关于当 CAAnimationGroup 的执行完成时,它会回到初始动画序列,并带有抽搐效果的主要内容,如果未能解决你的问题,请参考以下文章
CAAnimationGroup 与 CAKeyframeAnimation 和 CABasicAnimation
使用 CAAnimationGroup 对两个核心动画进行分组会导致一个 CABasicAnimation 无法运行
iOS 旋转动画在 CAAnimationGroup 中发生不顺畅