我想实现的动画,当你按下一个按钮,它动画块下来,当你松开,它蓬勃生机回升到原来的位置,但我不能获得动画块的当前位置,不管是什么。 这里是我的代码:
-(IBAction)moveDown:(id)sender{
CGRect position = [[container.layer presentationLayer] frame];
[movePath moveToPoint:CGPointMake(container.frame.origin.x, position.y)];
[movePath addLineToPoint:CGPointMake(container.frame.origin.x, 310)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = NO;
moveAnim.fillMode = kCAFillModeForwards;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, nil];
animGroup.duration = 2.0;
animGroup.removedOnCompletion = NO;
animGroup.fillMode = kCAFillModeForwards;
[container.layer addAnimation:animGroup forKey:nil];
}
-(IBAction)moveUp:(id)sender{
CGRect position = [[container.layer presentationLayer] frame];
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:CGPointMake(container.frame.origin.x, position.y)];
[movePath addLineToPoint:CGPointMake(container.frame.origin.x, 115)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = NO;
moveAnim.fillMode = kCAFillModeForwards;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, nil];
animGroup.duration = 2.0;
animGroup.removedOnCompletion = NO;
animGroup.fillMode = kCAFillModeForwards;
[container.layer addAnimation:animGroup forKey:nil];
}
但行
CGRect position = [[container.layer presentationLayer] frame];
只返回目的地位置不是当前位置。 我需要基本上给我的容器这就是动画一旦我松开按钮的当前位置,这样我就可以进行下一个动画。 我现在不工作。
我还没有分析你的代码足以成为100%肯定,为什么[[container.layer presentationLayer] frame]
可能不会返回你所期望的。 但是,我看到几个问题。
一个明显的问题是, moveDown:
没有声明movePath
。 如果movePath
是一个实例变量,你可能要清除或创建一个新的实例每次moveDown:
叫,但我没有看到你这样做。
一个不太明显的问题是,(从你使用的判断removedOnCompletion
和fillMode
,尽管你使用的presentationLayer
),你显然不明白的Core Animation是如何工作的。 这被证明是非常普遍的,所以请原谅我,如果我错了。 无论如何,请继续阅读,因为我将解释如何动画作品的核心,然后如何解决你的问题。
在核心动画,你通常与工作层的对象是一个模型层 。 当您将动画层,核心动画创建模型层的副本,称为表示层和动画随时间变化的展现层的性能。 动画永远不会改变模型层的特性。
当动画结束,并且(默认)被移除时,表示层被破坏,模型层的属性的值再次生效。 所以在屏幕上层出现“弹回”到原来的位置/颜色/不管。
解决这个问题的一个常见的,但错误的方法是设置动画的removedOnCompletion
到NO
及其fillMode
到kCAFillModeForwards
。 当你这样做时,表示层徘徊,所以没有在屏幕上“弹回”。 问题是,现在你有表示层比模型层不同的值游逛。 如果你问的动画属性值的模型层(或拥有它的视图),你会得到一个值,比在屏幕上有什么不同。 如果你尝试再次动画属性,动画可能会从错误的地方开始。
要动态图层属性,并使其“棒”,你需要改变模型层的属性值,然后应用动画。 这样一来,当动画被删除,并表示层消失,屏幕上的层看起来一模一样,因为模型层具有相同的属性值作为其表现层有当动画结束。
现在,我不知道为什么你使用关键帧动画的直线运动,或者为什么您使用的是动画组。 似乎都不需要在这里。 而你的两种方法实际上是一致的,所以让我们分解出公共代码:
- (void)animateLayer:(CALayer *)layer toY:(CGFloat)y {
CGPoint fromValue = [layer.presentationLayer position];
CGPoint toValue = CGPointMake(fromValue.x, y);
layer.position = toValue;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:fromValue];
animation.toValue = [NSValue valueWithCGPoint:toValue];
animation.duration = 2;
[layer addAnimation:animation forKey:animation.keyPath];
}
请注意,我们给了动画的关键,当我把它添加到层。 由于我们使用相同的密钥每一次,每一个新的动画将取代(删除)之前的动画,如果动画之前还没有完成。
当然,只要你玩这个,你会发现,如果你moveUp:
当moveDown:
只完成了一半,在moveUp:
动画会显得速度的一半,因为它仍然有2秒的持续时间,但只有一半远的旅行。 我们应该根据要行驶的距离真正计算时间:
- (void)animateLayer:(CALayer *)layer toY:(CGFloat)y withBaseY:(CGFloat)baseY {
CGPoint fromValue = [layer.presentationLayer position];
CGPoint toValue = CGPointMake(fromValue.x, y);
layer.position = toValue;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:fromValue];
animation.toValue = [NSValue valueWithCGPoint:toValue];
animation.duration = 2.0 * (toValue.y - fromValue.y) / (y - baseY);
[layer addAnimation:animation forKey:animation.keyPath];
}
如果你真的需要它是一个动画组中的keyPath动画,你的问题应该告诉我们你为什么需要这些东西。 无论如何,它与那些东西太多:
- (void)animateLayer:(CALayer *)layer toY:(CGFloat)y withBaseY:(CGFloat)baseY {
CGPoint fromValue = [layer.presentationLayer position];
CGPoint toValue = CGPointMake(fromValue.x, y);
layer.position = toValue;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:fromValue];
[path addLineToPoint:toValue];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.path = path.CGPath;
animation.duration = 2.0 * (toValue.y - fromValue.y) / (y - baseY);
CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = animation.duration;
group.animations = @[animation];
[layer addAnimation:group forKey:animation.keyPath];
}
你可以找到我的测试程序的完整代码在这个要点 。 只要创建一个新的单一视图应用项目和替换的内容ViewController.m
与要点的内容。