Core animation 从CATTransform3D到CGAffineTransform

Core animation 从CATTransform3D到CGAffineTransform,core-animation,core-graphics,Core Animation,Core Graphics,我使用以下函数将脉冲效果应用于视图 - (void)pulse { CATransform3D trasform = CATransform3DScale(self.layer.transform, 1.15, 1.15, 1); trasform = CATransform3DRotate(trasform, angle, 0, 0, 0); CABasicAnimation *animation = [CABasicAnimation animationWithK

我使用以下函数将脉冲效果应用于视图

- (void)pulse {

    CATransform3D trasform = CATransform3DScale(self.layer.transform, 1.15, 1.15, 1);
    trasform = CATransform3DRotate(trasform, angle, 0, 0, 0);

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    animation.toValue = [NSValue valueWithCATransform3D:trasform];
    animation.autoreverses = YES;
    animation.duration = 0.3;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.repeatCount = 2;
    [self.layer addAnimation:animation forKey:@"pulseAnimation"];

}

我希望使用CGAffineTransform self.transform而不是CATTransform3D self.layer.transform获得相同的结果。这可能吗?

当然可以。如果您在Xcode文档中搜索CGAffineTransform,您会发现一个标题为“CGAffineTransform参考”的章节。该章中有一节称为“功能”。它包括与CATTransformM3DScale(CGAffineTransformScale)和CATTransformM3DROATE(CGAffineTransformRotate)等效的函数

请注意,您对CATTransferM3Drotate的调用实际上没有意义。您需要绕一个轴旋转,并且所有3个轴都将通过0。通常,您希望使用CATTransform M3dRotate(变换形式、角度、0、0、1.0)绕Z轴旋转。引用文件:

如果向量长度为零,则行为未定义


可以将
CATTransform3D
转换为
CGAffineTransform
,但会丢失一些功能。我发现将层及其祖先的聚合转换转换为
cGraffinetTransform
非常有用,这样我就可以用核心图形渲染它。制约因素包括:

  • 您的输入在XY平面中将被视为平面
  • 您的输出在XY平面中也将被视为平面
  • .m34
    中的透视/缩短将被抵消
如果这听起来符合您的目的:

    // m13, m23, m33, m43 are not important since the destination is a flat XY plane.
    // m31, m32 are not important since they would multiply with z = 0.
    // m34 is zeroed here, so that neutralizes foreshortening. We can't avoid that.
    // m44 is implicitly 1 as CGAffineTransform's m33.
    CATransform3D fullTransform = <your 3D transform>
    CGAffineTransform affine = CGAffineTransformMake(fullTransform.m11, fullTransform.m12, fullTransform.m21, fullTransform.m22, fullTransform.m41, fullTransform.m42);

您可以使用CATTransformM3dGetAffiNetTransform将CATTransform3D转换为CGAffineTransform

let scaleTransform = CATransform3DMakeScale( 0.8, 0.8, 1)
imageview.transform = CATransform3DGetAffineTransform(scaleTransform)

出于好奇,如果你将CATTransferM3D应用于一个图层,而将CGAffineTransform应用于一个视图,如果你已经从前者获得了你想要的结果,你为什么会在意呢?因为self.layer.transform的初始值不同于self.transform,不是吗?我的意思是,在使用pulse方法之前,我对视图应用了一些仿射变换,但我不接触图层,因此我猜变换就是我所知道的,应用于视图的变换被转换为底层的适当CATTransform3D。通过对视图应用转换,然后运行上面的动画(当然要删除非功能性的
catTransferrM3dRotate()
),很容易验证这一点。它应该基于UIView之前的转换。谢谢,我的代码有点不清楚,我得到了错误的动画。因此,我猜测这两种转换(图层和视图)是不同的,但我显然错了。谢谢但问题的关键(我的问题可能不太清楚)是如何拥有与[CamediaTimingFunctionWithName:kCAMediaTimingFunctionEaseInEaseOut]等价的函数;你真的不清楚。我猜CGAffineTransform用于视图,CATTransform3D用于层,您想知道如何制作基于视图的动画,指定不同的计时函数。为此,您希望使用animateWithDuration:delay:options:animations:completion:UIView类方法。options参数包括UIViewAnimationOptionCurveEaseInOut、UIViewAnimationOptionCurveLinear等值。只需指定所需的选项,然后在animations块中更改变换。谢谢,这是正确的答案。不幸的是,它是应该包含在Cocoa API中的函数之一,但不是,因为它不是一个“完整”的转换(而且永远不可能)。我很高兴我发现了这一点。我已经搜索“3d到2d矩阵”一周了,刚发现了一堆数学上的胡言乱语。你他妈的是怎么知道的?这太棒了!我向你的数学天才致敬。
let scaleTransform = CATransform3DMakeScale( 0.8, 0.8, 1)
imageview.transform = CATransform3DGetAffineTransform(scaleTransform)