Как сделать Catransform3DMakerotation повернуть другой путь? И цепочка вместе

StackOverflow https://stackoverflow.com/questions/3799194

Вопрос

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

я использую CATransaction С некоторым успехом - в фрагменте ниже, карта движется от нижней части слева вверху влево и переворачивает. Проблема в том, что я не хочу переворачивать обратный путь, но не знаю, как это сказать: «Эй, ты идешь неправильно!»


[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration];
myCard.position = CGPointMake(CGRectGetMidX(self.bounds)/2,CGRectGetMidY(self.bounds)/2);
myCard.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
[CATransaction commit]; 

Второй вопрос будет: как я могу получить его сразу два преобразования? Я пытался вложить два CATransactions, но второй просто переопределяет первый. Я также попробовал изменение вектора для вращения, чтобы быть 2D, как сказать, чтобы повернуть вокруг оси X и Y, но это не эквивалентно просто переворачивать его на Pi вокруг двух отдельных осей. Вот вложенный код.


[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration];
myCard.position = CGPointMake(CGRectGetMidX(self.bounds)/2,CGRectGetMidY(self.bounds)/2);
myCard.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0); // rotate about x

  [CATransaction begin]; 
  [CATransaction setValue:[NSNumber numberWithFloat:1.0f] forKey:kCATransactionAnimationDuration];
  myCard.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0); // rotate about y
  [CATransaction commit]; 

[CATransaction commit]; 

И вот это с UIView Анимационные блоки внутри ... Я добавил ползунки для угла, x, y, z для вектора вращения и t для времени. Перевод происходит со временем = 2T, и каждая из вращений должна взять только в каждой.

[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:t * 2] forKey:kCATransactionAnimationDuration];
myCard.position = CGPointMake(CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2);

  [UIView beginAnimations:nil context:nil];
  [UIView setAnimationDuration:t];
  myCard.transform = CATransform3DMakeRotation(angle, x, y, z);
  [UIView commitAnimations]; 

  [UIView beginAnimations:nil context:nil];
  [UIView setAnimationDuration:t];
  [UIView setAnimationDelay:t];
  myCard.transform = CATransform3DMakeRotation(angle * 2, x, y, z);
  [UIView commitAnimations];

[CATransaction commit]; 

И это где я сейчас: все работает одним исключением. Реверс вращения Y (начинает вращаться в противоположном направлении), когда карта попадает в PI / 2 и 3 * PI / 2. Он также переворачивается о оси X в этих точках. Но X и Z отлично работают. Так близко!

CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL,CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*3);
CGPathAddCurveToPoint(thePath,NULL,
                      CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*2,
                      CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*1.5,
                      CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2);
CAKeyframeAnimation *moveAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnimation.path=thePath;
CFRelease(thePath);

CABasicAnimation *xRotation;
xRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
xRotation.fromValue = [NSNumber numberWithFloat:0.0];
xRotation.toValue = [NSNumber numberWithFloat:x * angle * M_PI];

CABasicAnimation *yRotation;
yRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
yRotation.fromValue = [NSNumber numberWithFloat:0.0];
yRotation.toValue = [NSNumber numberWithFloat:y * angle * M_PI];

CABasicAnimation *zRotation;
zRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
zRotation.fromValue = [NSNumber numberWithFloat:0.0];
zRotation.toValue = [NSNumber numberWithFloat:z * angle * M_PI];

CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.duration = t;
groupAnimation.removedOnCompletion = NO;
groupAnimation.fillMode = kCAFillModeForwards;
groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
groupAnimation.animations = [NSArray arrayWithObjects:moveAnimation, xRotation, yRotation, zRotation, nil];

[myCard addAnimation:groupAnimation forKey:@"animateCard"];
Это было полезно?

Решение

Я считаю, что то, что вы хотите в этом случае, состоит в том, чтобы использовать хелперскую клавиатую, как описано в Этот ответ:

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI];
rotationAnimation.duration = duration;
[myCard.layer addAnimation:rotationAnimation forKey:@"rotationAnimation1"];

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

CABasicAnimation *rotationAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
rotationAnimation2.toValue = [NSNumber numberWithFloat: M_PI];
rotationAnimation2.duration = duration2;
rotationAnimation2.cumulative = YES;
[myCard.layer addAnimation:rotationAnimation2 forKey:@"rotationAnimation2"];

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

Когда вы работаете с напрямую преобразование, основная анимация будет интерполировать преобразование от текущего значения в указанное преобразование. Он найдет самый короткий путь, чтобы добраться до этого преобразования, который ограничит направление анимации. Если вы попытаетесь анимировать тот же свойство преобразования дважды, второе значение будет просто переопределить первое, а не объединить два преобразования вместе.

Однако при использовании хелперной клавиатуры, как это, основная анимация будет интерполировать между исходным углом и углом окончания, поэтому вы можете обратить вспять направление, изменив знак окончания угла. Он оптимизирует изменение значения угла, а не изменение в базовом преобразовании. Вы также должны быть в состоянии объединить анимацию на клавиатуре, потому что преобразование генерируется для вас под капотом для каждой комбинации манипуляций клавиатуры.

Другие советы

Я предполагаю, что листовка на оси вызвана гимбальным замком, происходящим внутри библиотеки Apple. Простое исправление, которое работает 99,999% времени, заключается в том, чтобы просто не использовать точные 0, 90, 180, 270 и 360 градусов вращений. Я видел такие вещи, как это происходит в моем коде, но я просто использую что-то вроде (m_pi * 0,99) вместо m_pi. Это всегда проблема, если вы используете матрицы видеокарты с углом EULER.

Чтобы применить несколько преобразований одновременно, вы можете закрыть их. Это работает точно так же, как размножающие матрицы в OpenGL.

// translate and scale at the same time
float scale = 1.6;
CATransform3D scaleMatrix = CATransform3DMakeScale(scale, scale, 1);
CATransform3D finalMatrix = CATransform3DTranslate(scaleMatrix, frame.size.width/scale, frame.size.height/scale, 0);
CABasicAnimation* animBottomTrans = [CABasicAnimation animationWithKeyPath:@"transform"];
[animBottomTrans setFromValue:[NSValue valueWithCATransform3D:finalMatrix]];
[animBottomTrans setToValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
[animBottomTrans setDuration:duration];
[myLayer addAnimation:animBottomTrans forKey:@"transform"];

Помните, что, поскольку они вложены, вы должны иметь дело с предыдущим преобразованием в любых преобразованиях, которые приходят после нее. В этом коде я должен изменить сумму, которую я перевел, потому что я уже масштабировался. Если вы вращаете 90 градусов на Z оси Z, а затем поверните на 90 градусов на оси Y, вы эффективно повернули на осях z и x (вращение Z сворачивает ваш ось X и Y).

Полученное преобразование одинаково: (CGAffineTransform){-1,0,0,-1,0,0}. Отказ Кореанация выбирает самое короткое вращение, которое будет делать трюк, и по умолчанию для вращения по часовой стрелке (я думаю).

Самый простой способ вращения другого способа вращаться почти -M_PI (Я не уверен, что именно насколько близко вы можете получить, прежде чем он решит повернуть «неправильный путь).

Чем более сложный способ - сломать его на два вращения: от 0 до -M_PI / 2 и один из -M_PI / 2 до -M-PI. Я думаю, что вы можете установить задержку анимации, чтобы сделать это ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top