我使用CABasicAnimation对存储在数组中的CAShapeLayers
的颜色进行动画处理。动画根据animation.duration
不规则地显示,我不知道为什么。我怀疑animation.beginTime = CACurrentMediaTime() + delay
动画说明
动画包含连续闪烁的形状为黄色,然后在动画结束后将其变为黑色。
动画的当前状态
当动画持续时间超过特定时间时,它将正常工作。
但是当我缩短持续时间时,结果会大不相同。
您会注意到,动画已经缓存/结束了大约前10个小节,然后等待并开始为其余形状设置动画。
在这种情况下,似乎一定数量的动画已经结束(形状为黑色),然后在一定时间后显示某些动画。您还可以注意到,尽管形状彩色动画应该持续相同的持续时间(0.5s),但有些感觉比其他动画要快。
代码
在UIViewController类的viewDidAppear方法中调用动画。
我创建了一个UIView自定义类来绘制形状,并使用该类的扩展对其进行动画处理。
动画颜色的代码:
enum ColorAnimation{
case continuousSwap
case continousWithNewColor(color: UIColor)
case randomSwap
case randomWithNewColor(color: UIColor)
case randomFromUsedColors
}
func animateColors(for duration: Double,_ animationType: ColorAnimation, colorChangeDuration swapColorDuration: Double){
guard abs(swapColorDuration) != Double.infinity else {
print("Error in defining the shape color change duration")
return
}
let animDuration = abs(duration)
let swapDuration = abs(swapColorDuration)
let numberOfSwaps = Int(animDuration / min(swapDuration, animDuration))
switch animationType {
case .continousWithNewColor(color: let value):
var fullAnimation = [CABasicAnimation]()
for i in (0...numberOfSwaps) {
let index = i % (self.pLayers.count)
let fromValue = pLayers[index].pattern.color
let delay = Double(i) * swapDuration / 3
let anim = colorAnimation(for: swapDuration, fromColor: value, toColor: fromValue, startAfter: delay)
fullAnimation.append(anim)
}
for i in (0...numberOfSwaps) {
CATransaction.begin()
let index = i % (self.pLayers.count)
CATransaction.setCompletionBlock {
self.pLayers[index].shapeLayer.fillColor = UIColor.black.cgColor
}
pLayers[index].shapeLayer.add(fullAnimation[i], forKey: "fillColorShape")
CATransaction.commit()
}
default:
()
}
}
将动画的整个持续时间除以颜色变化的持续时间(例如),如果整个动画为10s,每个形状的颜色更改为1s,则表示10个形状将更改颜色。 然后,我使用colorAnimation(for:fromColor,toColor,startAfter :)方法创建CABasicaAnimation对象。
func colorAnimation(for duration: TimeInterval, fromColor: UIColor, toColor: UIColor, reverse: Bool = false, startAfter delay: TimeInterval) -> CABasicAnimation {
let anim = CABasicAnimation(keyPath: "fillColor")
anim.fromValue = fromColor.cgColor
anim.toValue = toColor.cgColor
anim.duration = duration
anim.autoreverses = reverse
anim.beginTime = CACurrentMediaTime() + delay
return anim
}
最后,我将动画添加到适当的CAShapeLayer中。 显然可以对代码进行优化,但是我选择按以下步骤进行操作,以查找其无法正常工作的原因。
到目前为止的尝试
到目前为止,我已经尝试过:
在colorAnimation方法中设置animation.beginTime
和不设置CACurrentMediaTime()
,包括是否设置animation.beginTime
:如果我不使用CACurrentMediaTime
设置animation.delegate = self
,我根本看不到任何动画。
有和没有指向body {
margin: 40px;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
display: flex;
}
.header div {
display: flex;
flex-direction: column;
padding: 10px;
}
.footer {
grid-area: footer;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 50% 50%;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.header,
.footer {
background-color: #999;
}
的地方:它没有任何改变。
使用DispatchQueue(将动画存储在全局文件中,然后在main中运行它),并且怀疑形状没有动画。
我怀疑beginTime不能正常工作,但事实并非如此,或者仅仅是因为形状动画,形状动画的持续时间似乎有所变化,而它本来就不会。
非常感谢您对此问题的了解。任何想法都是欢迎的,即使它看起来牵强,也可以为解决这个问题提供新的方法!
最好
答案 0 :(得分:1)
实际上,持续时间和swapColorDuration之间有关系
func animateColors(for duration: Double,_ animationType: ColorAnimation, colorChangeDuration swapColorDuration: Double)
在调用它时,您可能需要保持这种关系
let colorChangeDuration: TimeInterval = 0.5
animateColors(for: colorChangeDuration * TimeInterval(pLayers.count), .continousWithNewColor(color: UIColor.black), colorChangeDuration: colorChangeDuration)
也在这里:
let numberOfSwaps = Int(animDuration / min(swapDuration, animDuration)) - 1
此值可能比您需要的高。
或
问题出在let index = i % (self.pLayers.count)
if numberOfSwaps > self.pLayers.count
,某些乐队将是双重动画。
let numberOfSwaps1 = Int(animDuration / min(swapDuration, animDuration))
let numberOfSwaps = min(numberOfSwaps1, self.pLayers.count)
其余的是
for i in (0..<numberOfSwaps) {... }
现在为numberOfSwaps < self.pLayers.count
。还没结束。
如果numberOfSwaps较大,则可以。
如果需要双重动画,请更改以下内容:
pLayers[index].shapeLayer.add(fullAnimation[i], forKey: nil)
或pLayers[index].shapeLayer.add(fullAnimation[i], forKey: "fillColorShape" + String(i))