不要发布关于动画的答案我理解UIView,我正在学习核心动画。我试图让图像向右移动50个单位,但我遇到了很多问题。首先,当调用动画时,图像跳转到新位置,运行,然后跳回原始位置。我希望它只是向右移动50个单位,如果按下按钮则停止,再次移动。我花了很多时间研究,似乎无法找到问题。我的代码:
-(IBAction)preform:(id)sender{
CGPoint point = CGPointMake(imView.frame.origin.x, imView.frame.origin.y);
imView.layer.position = point;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
anim.fromValue = [NSValue valueWithCGPoint:point];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(point.x + 50, point.y)];
anim.duration = 1.5f;
anim.repeatCount =1;
anim.removedOnCompletion = YES;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[imView.layer addAnimation:anim forKey:@"position.x"];
imView.layer.position = point;
}
答案 0 :(得分:16)
我在你的代码中看到了几个问题。
首先,你正在抓住这样的帧起源:
CGPoint point = CGPointMake(imView.frame.origin.x, imView.frame.origin.y);
虽然这不是一个真正的问题,但你可以这样做:
CGPoint point = imView.frame.origin;
问题在于您将图层的position
设置为其框架的原点。但默认情况下,位置控制视图的中心,框架的原点是左上角。您可能想要首先获取图层的位置:
CGPoint point = imView.layer.position; // equivalent to imView.center
其次,您使用的是position.x
密钥路径,该路径需要CGFloat
值,但您提供的值为CGPoint
。这似乎不会导致iOS 6.1模拟器出现问题,但假设它始终有效可能是一个坏主意。
第三,您需要了解动画不会更改图层的属性!您通常操作的每个图层(技术上称为模型图层)都有一个关联的表示图层。表示层的属性控制屏幕上的内容。当您更改模型图层的属性时,Core Animation通常会自动在表示层上设置动画(从旧值到新值)。这称为隐式动画。 UIView
会抑制其图层上的隐式动画。
当表示层上的动画结束并被删除时,表示层的属性将恢复为其模型层的值。因此,要使更改成为永久更改,您需要更新模型图层的属性。通常,最好先更新模型图层的属性,然后添加动画,以便显式动画覆盖隐式动画(如果创建了一个动画)。
碰巧,尽管您可以为position.x
制作动画,但您需要在position
图层上设置model
以使其保持活力。我测试了这个工作:
- (IBAction)perform:(id)sender {
CGPoint point0 = imView.layer.position;
CGPoint point1 = { point0.x + 50, point0.y };
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
anim.fromValue = @(point0.x);
anim.toValue = @(point1.x);
anim.duration = 1.5f;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// First we update the model layer's property.
imView.layer.position = point1;
// Now we attach the animation.
[imView.layer addAnimation:anim forKey:@"position.x"];
}
(请注意,我调用了我的方法perform:
。原帖中的方法似乎拼写错误。)
如果您想真正了解核心动画,我强烈建议您观看WWDC 2011中的Core Animation Essentials video。这是一个小时,包含大量有用的信息。
答案 1 :(得分:1)
这是你需要它才能使它工作。图层上的位置已经设置好,因此您可以将其用作fromValue
,只需修改它即可获得toValue
。另一个重要步骤是将图层位置设置为endPos
,以便在动画完成时,图像视图将保持在正确的位置。
-(IBAction)preform:(id)sender
{
CGPoint startPos = imView.layer.position;
CGPoint endPos = CGPointMake(point.x + 50, point.y);
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
anim.fromValue = [NSValue valueWithCGPoint:startPos];
anim.toValue = [NSValue valueWithCGPoint:endPos];
anim.duration = 1.5f;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[imView.layer addAnimation:anim forKey:@"position.x"];
imView.layer.position = endPos;
}
答案 2 :(得分:-1)
跳回是由于您在完成时删除动画
anim.removeOnCompletion = NO;
编辑#3:刚刚复制并尝试了你的代码,这是你所有问题的解决方法,非常自我解释:
CGPoint point = imView.center;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
anim.fromValue = [NSNumber numberWithFloat:point.x];
anim.toValue = [NSNumber numberWithFloat:point.x+50.0];//[NSValue valueWithCGPoint:CGPointMake(point.x + 50, point.y)];
anim.duration = 1.5f;
anim.repeatCount =1;
anim.removedOnCompletion = NO;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
anim.fillMode=kCAFillModeForwards;
[imView.layer addAnimation:anim forKey:@"position.x"];
[sender.layer addAnimation:anim forKey:@"position.x"];
sender.layer.position=CGPointMake(point.x+50.0,sender.layer.position.y);
即使将removeOnCompletion设置为no,它也会跳回去,这是一个令人头疼的问题。仍然在玩它。