Направление вращения Force CALayer? - PullRequest
5 голосов
/ 15 июля 2010

Этот сводит меня с ума ...

Учитывая, что "плоскость" - это CALayer, я поворачиваю его по оси X:

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

И это заставляет его вращаться по часовой стрелке, что идеально.

Теперь, в какой-то момент времени, я хочу, чтобы оно вернулось к 0 градусам, поэтому я использую:

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

Дело в том ... это делает этопротив часовой стрелки, а это не то, что я хочу: (

Я предполагаю, что он использует кратчайший путь вращения, но даже если я скажу ему вместо этого повернуться на 360 градусов, когда это будет сделано, и я скажу этоперезапустите анимацию, она начинается с 360, чтобы перейти к 180, и она идет назад, а не в правильном направлении.

Есть ли способ обойти это?

Что бы я сделал в Actionscript будет выглядеть следующим образом:

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

И он возобновится, но если я сделаю это, используя CATransform3DMakeRotation , то оба преобразования столкнутся из-за анимации (я думаю)и это испортилось.

Любая помощь будет высоко ценится!

Спасибо

Ответы [ 3 ]

8 голосов
/ 07 сентября 2011

Этот вопрос возник, когда я искал, чтобы решить аналогичную проблему. Я хотел повернуть изображение на 180 градусов, а затем хотел продолжать совершать полное сальто. iOS хотела вернуться по кратчайшему маршруту. Ответ здесь не очень помог мне. Я закончил поиском некоторых вещей по анимации keyPath, и это решило мою проблему. Ниже приведен пример подхода.

Для конкретной проблемы, поднятой в вопросе, вам понадобятся два разных набора keyFrameValues, один для начального поворота, а другой для второго. Но, введя промежуточное значение, вы можете получить желаемый эффект, то есть выбрать более длинный путь или принудительно выбрать одинаково длинные пути, если вы этого хотите. Я оставил несколько вариантов кода в комментариях, так как они могут помочь людям, не знакомым с 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;
}
1 голос
/ 17 июля 2010

Я думаю, что ваша проблема сводится к ожиданию слишком большого количества неявной системы анимации, которая в основном просто интерполирует значения свойств вашего слоя от A до B. Это отлично подходит для широкого спектра случаев, но это не так. не позволяют вам делать такие вещи, как «цепные» изменения вместе в последовательности. Есть способы сделать последнее, хотя они определенно менее удобны, чем то, что вы делаете в данный момент. Тем не менее, вы можете захотеть исследовать тех, кто делает вещи "правильно". (Начните с другого взгляда на Core Animation Guide .)

Однако, если вы готовы смириться с обходным обходным путем, вы могли бы иметь возможность выглядеть так, как вы хотите, просто продолжая каждый раз менять угол поворота в одном и том же направлении. вместо того, чтобы устанавливать его на постоянное значение 0 или 180:

// 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);

Я говорю «может», потому что что-то в вашем описании не соответствует тому, как я ожидал бы преобразования, чтобы работать, и есть некоторые тонкости реализации, которые я не понимаю должным образом. Такой подход вполне может провалиться. Но это тривиально просто, так что, вероятно, стоит попробовать.

0 голосов
/ 18 января 2018

У меня работает такое решение.Вы добавляете промежуточное значение вращения, чтобы показать, в каком направлении должен поворачиваться вид.Так что вам не нужно 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)
}
...