我有一个正方形的CAShapeLayer
,我将width
设置为2.0f。
我想为其strokeEnd
设置动画,为此我使用CABasicAnimation
,如此:
CABasicAnimation *stroke = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
stroke.fromValue = @(0);
stroke.toValue = @(1);
stroke.repeatCount = 1;
stroke.duration = 10.0f;
stroke.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[myLayer addAnimation:stroke forKey:nil];
它有效。从Matt Neuberg的书中我知道我们可以完全省略toValue
和fromValue
:
[CATransaction begin];
[CATransaction setDisableActions:YES];
..
..
[CATransaction commit];
然而,他的例子基于transform
。我试图用strokeEnd
来实现相同的目标。
我能做的最好的事情是将strokeEnd
块中的CATransaction
设置为1或0并相应地设置fromValue
。其他的话我似乎无法在动画toValue
上省略endValue
和strokeEnd
- 我至少需要其中一个(即fromValue
或{{1 }})。
所以我的问题是,我怎样才能动画toValue
而无需使用strokeEnd
和toValue
?
感谢。
答案 0 :(得分:12)
这里有两个非常不同的问题:
如果您更改了某个图层的可动画属性(即不使用CABasicAnimation
,而是直接在代码中更改图层的属性),Core Animation可能会将隐式动画应用于图层(相对较快)动画,但动画但是)。例如,如果更改myLayer.opacity
,Core Animation可能会自动应用隐式动画来淡化此效果。同样,如果您直接更改myLayer.strokeEnd
,它可能会为笔画结束的变化设置动画(您会看到它快速绘制线条,而不是立即显示)。
通过使用[CATransaction setDisableActions:YES]
,您可以指示Core Animation不执行直接更改图层属性时可能应用的隐式动画。使用[CATransaction setDisableActions:NO]
,您将重新启用隐式动画。
创建CABasicAnimation
时,有fromValue
,toValue
和byValue
属性(根据文档,“所有都是可选的,并且不超过两个应该是非nil
。“)。您经常会看到指定fromValue
和toValue
的动画。但是你想要,你可以指定一个,而Core Animation将决定其他人应该是什么。
例如,我们假设您刚刚创建了CAShapeLayer
(默认情况下,strokeEnd
为1.0
)。然后,如果我想将strokeEnd
的动画设置为0到100%,您可以使用:
CABasicAnimation *stroke = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
stroke.fromValue = @(0.0);
stroke.duration = 1.0f;
[myLayer addAnimation:stroke forKey:nil];
注意,我不必指定toValue
的{{1}},因为它会自动默认为@(1.0)
的当前值(在此示例中恰好为1.0)。
核心动画的这两个截然不同的方面是你使用myLayer.strokeEnd
编写动画的时候,你不仅想要指定动画,而且还想改变图层的属性,直接,在动画开始之前。
例如,如果我添加CABasicAnimation
作为CAShapeLayer
,但想要为其前半部分的绘图设置动画(即将sublayer
从strokeEnd
设置为动画0.0
),您理论上可能希望(a)将0.5
指定为最终值(例如myLayer.shapeEnd
); (b)使用0.5
CABasicAnimation
创建fromValue
(但您可以省略@(0.0)
,因为我们已经将图层的toValue
设置为适当的shapeEnd
值)。但是,在我的答案开始时回到第1点,当我们直接设置图层属性时,例如myLayer.shapeEnd
,您可能希望setDisableActions
到YES
,所以没有尝试在任何隐式动画中(假设我们将使用CABasicAnimation
指定实际所需的动画)。
// set the layer's strokeEnd directly (with no implicit animation)
[CATransaction setDisableActions:YES];
myLayer.strokeEnd = 0.5;
[CATransaction setDisableActions:NO];
// now animate the layer's stroke end from 0.0 to the final value,
// which, because we didn't specify `toValue`, will default to the
// current value of `myLayer.strokeEnd` (which we happened to set
// right above)
CABasicAnimation *stroke = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
stroke.fromValue = @0.0;
stroke.duration = 1.0f;
[myLayer addAnimation:stroke forKey:nil];
在实践中,我发现setDisableActions
通常是不必要的,但从技术上讲,如果您正在设置图层的属性并且您想确保没有启动隐式动画,您可能希望使用{{1} },如上所示。
但是,正如您可能从此讨论中推断出的那样,我们不需要设置setDisableActions
的事实不是使用toValue
或其方法CATransaction
的直接结果。此示例中不需要setDisableActions
,因为我们在开始动画之前设置了图层toValue
。我们恰好使用strokeEnd
来确保在直接更改图层属性时没有启动隐式动画。