CABasicAnimation сбрасывается до начального значения после завершения анимации
я вращаю CALayer и пытаюсь остановить его в конечном положении после завершения анимации.
но после завершения анимации он сбрасывается в исходное положение.
(Xcode docs явно говорят, что анимация не будет обновлять значение свойства.)
любые предложения, как этого добиться.
13 ответов:
Edit: вот ответ, Это мой ответ и это Кришнан.
cabasicanimation.fillMode = kCAFillModeForwards; cabasicanimation.removedOnCompletion = NO;значение по умолчанию:
kCAFillModeRemoved. (Это поведение сброса, которое вы видите.)
проблема с removedOnCompletion заключается в том, что элемент пользовательского интерфейса не позволяет взаимодействовать с пользователем.
I метод состоит в том, чтобы установить значение FROM в анимации и значение TO на объекте. Анимация автоматически заполнит значение TO перед его запуском, и когда он будет удален, объект останется в правильном состоянии.
// fade in CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath: @"opacity"]; alphaAnimation.fillMode = kCAFillModeForwards; alphaAnimation.fromValue = NUM_FLOAT(0); self.view.layer.opacity = 1; [self.view.layer addAnimation: alphaAnimation forKey: @"fade"];
просто поместите его в свой код
CAAnimationGroup *theGroup = [CAAnimationGroup animation]; theGroup.fillMode = kCAFillModeForwards; theGroup.removedOnCompletion = NO;
вы можете просто установить ключ
CABasicAnimationtopositionкогда вы добавляете его в слой. Сделав это, он переопределит неявную анимацию, выполненную на позиции для текущего прохода в цикле выполнения.CGFloat yOffset = 30; CGPoint endPosition = CGPointMake(someLayer.position.x,someLayer.position.y + yOffset); someLayer.position = endPosition; // Implicit animation for position CABasicAnimation * animation =[CABasicAnimation animationWithKeyPath:@"position.y"]; animation.fromValue = @(someLayer.position.y); animation.toValue = @(someLayer.position.y + yOffset); [someLayer addAnimation:animation forKey:@"position"]; // The explicit animation 'animation' override implicit animationвы можете получить дополнительную информацию о 2011 Apple WWDC Video Session 421-Core Animation Essentials (середина видео)
просто задание
fillModeиremovedOnCompletionне работает для меня. Я решил проблему, установив все из приведенных ниже свойств объекта CABasicAnimation:CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"]; ba.duration = 0.38f; ba.fillMode = kCAFillModeForwards; ba.removedOnCompletion = NO; ba.autoreverses = NO; ba.repeatCount = 0; ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.85f, 0.85f, 1.0f)]; [myView.layer addAnimation:ba forKey:nil];этот код преобразует
myViewдо 85% от его размера (3-й размер неизменен).
@ответ Лесли Годвина не очень хорош, " сам.вид.слой.непрозрачность = 1; " делается немедленно (это занимает около одной секунды), пожалуйста, исправьте alphaAnimation.продолжительность 10.0, если у вас есть сомнения. Вы должны удалить эту строку.
Итак, когда вы исправляете fillMode в kCAFillModeForwards и removedOnCompletion в NO, вы позволяете анимации оставаться в слое. Если вы исправите делегат анимации и попробуете что-то вроде:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { [theLayer removeAllAnimations]; }...слой восстанавливается сразу же на момент, когда вы выполняете эту строку. Это то, чего мы хотели избежать.
вы должны исправить свойство слоя, прежде чем удалить анимацию из него. Попробуйте это:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { if([anim isKindOfClass:[CABasicAnimation class] ]) // check, because of the cast { CALayer *theLayer = 0; if(anim==[_b1 animationForKey:@"opacity"]) theLayer = _b1; // I have two layers else if(anim==[_b2 animationForKey:@"opacity"]) theLayer = _b2; if(theLayer) { CGFloat toValue = [((CABasicAnimation*)anim).toValue floatValue]; [theLayer setOpacity:toValue]; [theLayer removeAllAnimations]; } } }
CALayer имеет слой модели и слой представления. Во время анимации слой представления обновляется независимо от модели. По завершении анимации слой представления обновляется значением из модели. Если вы хотите избежать резкого скачка после окончания анимации, ключ должен держать два слоя в синхронизации.
если вы знаете конечное значение, вы можете просто установить модели напрямую.
self.view.layer.opacity = 1;но если у вас есть анимация, где вы этого не делаете знайте конечную позицию (например, медленное затухание, которое пользователь может приостановить, а затем повернуть вспять), затем вы можете запросить слой представления непосредственно, чтобы найти текущее значение, а затем обновить модель.
NSNumber *opacity = [self.layer.presentationLayer valueForKeyPath:@"opacity"]; [self.layer setValue:opacity forKeyPath:@"opacity"];вытягивание значения из слоя представления также особенно полезно для масштабирования или поворота ключевых путей. (например,
transform.scale,transform.rotation)
без использования
removedOnCompletionВы можете попробовать этот метод:
self.animateOnX(item: shapeLayer) func animateOnX(item:CAShapeLayer) { let endPostion = CGPoint(x: 200, y: 0) let pathAnimation = CABasicAnimation(keyPath: "position") // pathAnimation.duration = 20 pathAnimation.fromValue = CGPoint(x: 0, y: 0)//comment this line and notice the difference pathAnimation.toValue = endPostion pathAnimation.fillMode = kCAFillModeBoth item.position = endPostion//prevent the CABasicAnimation from resetting item's position when the animation finishes item.add(pathAnimation, forKey: nil) }
это работает:
let animation = CABasicAnimation(keyPath: "opacity") animation.fromValue = 0 animation.toValue = 1 animation.duration = 0.3 someLayer.opacity = 1 // important, this is the state you want visible after the animation finishes. someLayer.addAnimation(animation, forKey: "myAnimation")основная анимация показывает "презентационный слой" поверх вашего обычного слоя во время анимации. Поэтому установите непрозрачность (или что-то еще) на то, что вы хотите видеть, когда анимация заканчивается, и слой презентации уходит. Сделайте это на линии до добавить анимацию, чтобы избежать мерцания, когда он завершает.
Если вы хотите иметь задержку, выполните следующие действия:
let animation = CABasicAnimation(keyPath: "opacity") animation.fromValue = 0 animation.toValue = 1 animation.duration = 0.3 animation.beginTime = someLayer.convertTime(CACurrentMediaTime(), fromLayer: nil) + 1 animation.fillMode = kCAFillModeBackwards // So the opacity is 0 while the animation waits to start. someLayer.opacity = 1 // <- important, this is the state you want visible after the animation finishes. someLayer.addAnimation(animation, forKey: "myAnimation")наконец, если вы используете 'removedOnCompletion = false' он будет пропускать CAAnimations, пока слой в конечном итоге не будет удален - избегайте.
Итак, моя проблема заключалась в том, что я пытался повернуть объект на жесте панорамирования, и поэтому у меня было несколько одинаковых анимаций на каждом ходу. У меня оба
fillMode = kCAFillModeForwardsиisRemovedOnCompletion = falseно это не помогло. В моем случае, Я должен был убедиться, что ключ анимации отличается каждый раз, когда я добавляю новую анимацию:let angle = // here is my computed angle let rotate = CABasicAnimation(keyPath: "transform.rotation.z") rotate.toValue = angle rotate.duration = 0.1 rotate.isRemovedOnCompletion = false rotate.fillMode = kCAFillModeForwards head.layer.add(rotate, forKey: "rotate\(angle)")
похоже, что флаг removedOnCompletion установлен в false, а fillMode установлен в kCAFillModeForwards также не работает для меня.
после того, как я применяю новую анимацию на слое, анимирующий объект сбрасывается в исходное состояние, а затем анимируется из этого состояния. Что нужно сделать дополнительно, так это установить желаемое свойство слоя модели в соответствии со свойством слоя представления перед установкой новой анимации следующим образом:
someLayer.path = ((CAShapeLayer *)[someLayer presentationLayer]).path; [someLayer addAnimation:someAnimation forKey:@"someAnimation"];
основная анимация поддерживает две иерархии слоев: слой модели и уровень представления. Когда анимация выполняется, слой модели фактически не поврежден и сохраняет его начальное значение. По умолчанию анимация удаляется после ее завершения. Затем слой представления возвращается к значению слоя модели.
просто задание
removedOnCompletionдоNOозначает, что анимация не будет удален и памяти. Кроме того, модель уровень и уровень представления больше не будут синхронными, что может привести к потенциальным ошибкам.поэтому было бы лучше обновить свойство непосредственно на уровне модели до конечного значения.
self.view.layer.opacity = 1; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue = 0; animation.toValue = 1; [self.view.layer addAnimation:animation forKey:nil];если есть какая-либо неявная анимация, вызванная первой строкой кода выше, попробуйте отключить if:
[CATransaction begin]; [CATransaction setDisableActions:YES]; self.view.layer.opacity = 1; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue = 0; animation.toValue = 1; [self.view.layer addAnimation:animation forKey:nil]; [CATransaction commit];
- ссылка:
- Анимации Пояснил by objc.io.
- " iOS 7 Программирование раздвигает границы" Роб Нейпир и Мугунт Кумар.
Comments