两个 CGPaths / UIBeziers 之间的补间 / 插值

Posted

技术标签:

【中文标题】两个 CGPaths / UIBeziers 之间的补间 / 插值【英文标题】:Tweening / Interpolating between two CGPaths / UIBeziers 【发布时间】:2013-08-22 08:58:35 【问题描述】:

我有一个包含 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 询问这个?

【问题讨论】:

在不平凡的情况下,内置的路径变形很快就会变得毫无用处。请参阅此处描述的问题和解释:***.com/a/17864445/438982 确实如此,但就我而言,变形看起来不错... 【参考方案1】:

这实际上比您首先想到的要简单得多,并且使用“无”速度(暂停)的动画。现在,将暂停的动画添加到图层后,您可以更改时间偏移以跳转到动画中的特定时间。

如果您不打算自己运行动画(即仅手动控制它),我建议您将动画的持续时间更改为 1。这意味着您将时间偏移从 0 更改为 1 从0% 到 100%。如果您的持续时间为 0.3(如您的示例中所示),那么您可以将时间偏移设置为 0 到 0.3 之间的值。

实施

正如我上面所说,这个小技巧涉及的代码很少。

    (可选)将持续时间设置为 1.0 将图层的speed(是的,它们符合CAMediaTiming)或动画设置为0.0 在拖动手势或滑块期间(如我的示例)设置图层或动画的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

您可以在下面看到最终结果。编码愉快!

【讨论】:

太棒了,谢谢。我不知道 timeOffset 的存在。如果您打算单独使用动画,您会怎么做? @tarmes 这取决于交互的细节。您仍然可以暂停动画并更改时间偏移(在这种情况下从 0 到 0.3)。您可以通过再次将速度设置回 1 来恢复动画。如果动画在您想要与之交互时正在运行,那么您可以使用[layer convertTime:CACurrentMediaTime() fromLayer:nil] 获取当前值。请参阅this answer 了解更多信息。 这个伟大的技术启发了我做一个带有 ►(播放)或 ❚❚(暂停)图标的按钮,可以很好地在两者之间变形。查看实际操作:instagram.com/p/l6a8uDHDk7 这是来源:gist.github.com/raphaelschaad/9734463 @DavidRönnqvist,我在我的代码上实现了你的答案..但它不起作用.. CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"]; morph.duration = 1.0; // 第一步 morph.fromValue = [NSValue valueWithCGPoint: CGPointMake([cell.imgView center].x - 5.0f, [cell.imgView center].y)]; morph.toValue = [NSValue valueWithCGPoint: CGPointMake([cell.imgView center].x + 5.0f, [cell.imgView center].y)]; // [cell.imgView.layer addAnimation:morph forKey:@"来回变形形状"]; @user 这真是一个新问题。也就是说,您正在为路径设置动画,但添加 points 作为 to 值和 from 值。

以上是关于两个 CGPaths / UIBeziers 之间的补间 / 插值的主要内容,如果未能解决你的问题,请参考以下文章

使用 CGPaths 和 CAShapeLayers 动画绘制字母

使用 CALayer 显示 CGPaths 会影响 iOS 中的性能吗?

什么时候可以使用 CALayer.timeOffset

在uiview中缓存绘图

CSS/DIV:两个DIV之间如何添加阴影呢

C++ 计算两个日期之间的天数