简体   繁体   English

强制CALayer的旋转方向?

[英]Force CALayer's rotation direction?

This one has been driving me nuts... 这个让我疯了......

Considering "plane" is a CALayer, I rotate it in the X axis: 考虑到“平面”是一个CALayer,我在X轴上旋转它:

plane.transform = CATransform3DMakeRotation(180 * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);

And this makes it rotate clockwise, which is perfect. 这使它顺时针旋转,这是完美的。

Now, at some point in time, I want it to return to 0 degrees, so I use: 现在,在某个时间点,我希望它返回到0度,所以我使用:

plane.transform = CATransform3DMakeRotation(0 * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);

The thing is... it does it anti-clockwise, which is not what I want :( 事情是......它逆时针方向,这不是我想要的:(

I'm guessing it uses the shortest rotation path, but even if I tell it to go to 360 degrees instead, when it's done and I tell it to restart the animation, it starts from 360 to go to 180, and it goes backwards instead of the right direction. 我猜它使用最短的旋转路径,但即使我告诉它转向360度,当它完成并且我告诉它重新开始动画时,它从360开始转到180,然后它向后转正确的方向。

Is there a way to workaround that? 有办法解决这个问题吗?

What I'd do in Actionscript would be: 我在Actionscript中做的是:

if (plane.rotationX == 360) plane.rotationX = 0;

And it'd resume nicely, but if I do that using CATransform3DMakeRotation both transformations collide, because of the animation (I think) and it gets messed up. 并且它恢复得很好,但如果我使用CATransform3DMakeRotation这样做,两个转换都会发生冲突,因为动画(我认为)并且它会搞砸。

Any help would be much appreciated! 任何帮助将非常感激!

Thanks 谢谢

This question came up when I was searching to solve a similar issue. 当我在寻找解决类似问题的时候出现了这个问题。 I wanted to rotate an image 180 degrees and then wanted to keeping going around for a full somersault. 我想将图像旋转180度,然后想要保持完整的翻筋斗。 iOS wanted to take the shortest route back. iOS想要回到最短的路线。 The answer here didn't help me too much. 这里的答案对我没有多大帮助。 I ended up looking up some stuff on keyPath animations and that solved my issue. 我最终在keyPath动画上查找了一些东西,这解决了我的问题。 Below is an example of the approach. 以下是该方法的示例。

For the particular issue raised in the question, you'd need two different sets of keyFrameValues, one for the initial rotation and another for the second. 对于问题中提出的特定问题,您需要两组不同的keyFrameValues,一组用于初始旋转,另一组用于第二轮。 But by putting in an intermediate value you can get the desired effect, ie take the longer path or force the choice of equally long paths, if that's what you want. 但是通过设置一个中间值,您可以获得所需的效果,即采用更长的路径或强制选择同样长的路径,如果这是您想要的。 I've left some variant code in comments, as they may help folk not familiar with CAKeyFrameAnimation follow the code / understand the range of options. 我在评论中留下了一些变体代码,因为它们可以帮助不熟悉CAKeyFrameAnimation的人遵循代码/理解选项的范围。

- (void) somersault;
{

    CALayer* layer = [self layer];
    NSMutableArray* keyFrameValues = [NSMutableArray array];
    [keyFrameValues addObject:[NSNumber numberWithFloat:0.0]];
    //[values addObject:[NSNumber numberWithFloat:M_PI*0.5]];
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI]];
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI*1.5]];
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI*2.0]];

    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    [animation setValues:keyFrameValues];
    [animation setValueFunction:[CAValueFunction functionWithName: kCAValueFunctionRotateX]];// kCAValueFunctionRotateZ]];

    [animation setDuration:0.9];
    //[animation setTimingFunction: [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

    [layer addAnimation:animation forKey:nil];

    return;
}

I think your problem is down to expecting a little too much of the implicit animation system, which is basically just going to interpolate your layer property values from A to B. This is great for a wide variety of cases, but it doesn't allow you to do things like "chain" changes together in sequence. 我认为你的问题是期望隐式动画系统有点过多,这基本上只是将你的图层属性值从A插入到B.这对于各种各样的情况都很好,但它不允许你可以按顺序一起做“链”变化。 There are ways to do the latter, though they're definitely less convenient than what you're doing at the moment. 有办法做后者,虽然它们肯定不如你现在所做的那么方便。 Still, you might want to investigate those to do things "properly". 不过,你可能想要调查那些“正确”做事。 (Start with another look at the Core Animation Guide .) (从另一个核心动画指南开始 。)

However, if you're willing to put up with a cheesy workaround, you might be able to get this to look how you want just by continuing to change the rotation angle in the same direction each time rather than setting it to a constant 0 or 180 : 但是,如果你愿意忍受一个俗气的解决方法,你或许可以通过每次继续改变相同方向的旋转角度,而不是将其设置为常数0180

// you need to keep track of this somewhere in your code
// (I've made it static for simplicity, you should do something more sensible)
static long currentAngle = 0;

// rotate (another) 180 degrees
currentAngle += 180;
plane.transform = CATransform3DMakeRotation(currentAngle * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);

I say "might", because something in your description doesn't really chime with how I would expect the transform to work, and there are clearly some implementation subtleties I don't properly understand. 我说“可能”,因为你的描述中的某些东西并没有真正与我期望转换工作的方式相符,并且显然有一些实现细微之处,我无法理解。 This approach may well fail. 这种方法可能会失败。 But it's trivially simple, so probably worth a try. 但这很简单,所以值得一试。

For me works such solution. 对我来说,这样的解决方案 You add an intermediate rotation value to show in which direction the view should be rotated. 您可以添加中间旋转值以显示视图应旋转的方向。 So you don't need CAKeyframeAnimation . 所以你不需要CAKeyframeAnimation

if backwardDirection {
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
    view.transform = CGAffineTransform(rotationAngle: 0)
} else {
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM