使用核心动画在屏幕上移动UIImage



不要发布关于UIVIEW动画的答案我了解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;
}

我在您的代码中看到了一些问题。

首先,你像这样获取帧原点:

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模拟器中造成问题,但假设它始终有效可能是个坏主意。

第三,您需要了解动画不会更改层的属性!您通常操作的每个层(技术上称为模型层)都有一个相关的表示。表示层的属性控制屏幕上的内容。更改模型层的属性时,核心动画通常会自动在表示层上设置动画(从旧值到新值)。这称为隐式动画。UIView在其层上抑制隐式动画。

当表达层上的动画结束并被移除时,表达层的属性将恢复为其模型层的值。因此,要使更改永久化,需要更新模型层的特性。通常,最好先更新模型层的属性,然后添加动画,以便显式动画覆盖隐式动画(如果已创建)。

实际上,尽管可以设置position.x的动画,但需要在model层上设置position才能使其保持不变。我测试了这个工作:

- (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的核心动画精华视频。它长达一个小时,包含了大量有用的信息。

这是让它工作所需要的。层上的位置已经设置好了,因此您可以将其用作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;
}

跳回是由于在完成时删除动画

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

即使removedOnCompletion设置为no,它也会跳回来,这一事实令人头疼。还在玩。

最新更新