Tweening / 在两个CGPath / UIBezier之间插值

33

我有一个包含CGPath的CAShapeLayer。使用iOS内置动画,我可以轻松地将这个路径转变成另一个路径:

    CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"];
    morph.fromValue = (id)myLayer.path;
    mayLayer.path = [self getNewPath];
    morph.toValue = (id)myLayer.path;
    morph.duration = 0.3;
    [myLayer addAnimation:morph forKey:nil];

这很完美。

然而,我现在想在拖动操作期间逐渐转换这些路径。为了做到这一点,我需要能够在拖动过程中的任何时刻检索插值路径。 有没有办法向iOS询问这个?


在非平凡的情况下,路径的内置变形很快就变得无用了。请参见此处描述的问题和解释:http://stackoverflow.com/a/17864445/438982 - ipmcc
这是真的,但在我的情况下变形效果很好。 - tarmes
1个回答

88
这其实比你最初想象的要简单得多,并且使用带有“无”速度(暂停)的动画。现在,通过将暂停的动画添加到图层中,您可以更改时间偏移量以跳转到动画中的特定时间。
如果您不打算单独运行动画(即只手动控制它),我建议您将动画持续时间更改为1。这意味着当从0%移动到100%时,您将把时间偏移从0更改为1。如果您的持续时间为0.3(如您的示例中所示),则应将时间偏移设置为0和0.3之间的值。
实现: 1. (可选)将持续时间设置为1.0 2. 将图层(是的,它们符合CAMediaTiming)或动画的速度设置为0.0 3. 在拖动手势或滑块(如我的示例)期间,设置图层或动画的timeOffset(取决于您在步骤2中所做的操作)。
这就是我配置动画+形状图层的方式。
CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"];
morph.duration  = 1.; // Step 1
morph.fromValue = (__bridge id)fromPath;
morph.toValue   = (__bridge id)toPath;
[self.shapeLayer addAnimation:morph forKey:@"morph shape back and forth"];

self.shapeLayer.speed = 0.0; // Step 2

还有滑块的操作:

- (IBAction)sliderChanged:(UISlider *)sender {
    self.shapeLayer.timeOffset = sender.value; // Step 3
}
您可以在下面看到最终结果。愉快的编码!

enter image description here


太棒了,谢谢。我完全不知道timeOffset的存在。如果您打算单独使用动画,您会怎么做? - tarmes
@tarmes 这取决于交互的具体情况。你仍然可以暂停动画并改变时间偏移量(在这种情况下从0到0.3)。将速度设置回1即可恢复动画。如果当您想要与动画进行交互时它正在运行,则可以使用[layer convertTime:CACurrentMediaTime()fromLayer:nil]获取当前值。有关更多信息,请参见此答案 - David Rönnqvist
7
这个伟大的技巧启发我制作了一个带有►(播放)或❚❚(暂停)图标的按钮,可以很好地在两者之间进行变形。在这里可以看到它的效果:http://instagram.com/p/l6a8uDHDk7 这是源代码:http://gist.github.com/raphaelschaad/9734463 - Raphael Schaad
@user 这确实是一个新问题。也就是说,您正在将作为to值和from值来动画化路径。 - David Rönnqvist
1
在Swift中,只有当我更改图层的速度和时间偏移量而不是动画本身时,它才能正常工作。 - Giohji
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接