【问题标题】:Animation of a UIImage moving from one UIImageView to anotherUIImage 从一个 UIImageView 移动到另一个 UIImageView 的动画
【发布时间】:2012-03-18 18:35:08
【问题描述】:

我已经设法使用 [UIView animateWithDuration... 来完成我在 UI 中需要的动画。现在我想沿着弯曲的路径移动图像,整个 CAAnimation 集群对我来说看起来非常令人生畏。

如果有人能帮我填写我希望我能编码的方法,我将非常感激,它看起来像这样:

- (void)makeAnImageFlyFrom:(UIImageView *)imageViewA to:(UIImageView *)imageViewB alongPath:(CGMutablePathRef)path duration:(NSTimeInterval)duration {

    UIImage *imageToFly = imageViewA.image;
    // magic, that i'm too lazy to learn right now goes here
    // image flys along the path and gets scaled to match imageViewB.

    // then view/layer hierarchy is just as it was, but imageViewB has a new image
    // maybe this happens on animationDidStop...
    imageViewB.image = imageToFly;

}

如果您认为这种方法有更智能的界面,请随意替换参数(如路径引用)。提前致谢。

【问题讨论】:

  • 这几乎是构建 CAKeyframeAnimation 所需的信息,q.v。 developer.apple.com/library/mac/#documentation/GraphicsImaging/…
  • 我认为我现在得到的半页破碎的东西会更难回答(并且由于我的错误而将答案发送到错误的方向)然后要求一个干净的石板。在我看来,这似乎是一个特定的操作,有更多经验的人会很容易掌握他们的技巧。 CAAnimation、CALayer、CAAnimationGroup、CATimingFunction、CGPath 等是移动图像的一个相当大的学习曲线。是否有一个明显的答案,任何 rube 都应该花点时间想出答案?把它放在一个侮辱我的答案中,我会把它标记为正确的。

标签: iphone uiviewanimation caanimation


【解决方案1】:

好的,整个星期天之后,我认为这是一种可行的方法。我仍然不清楚一些东西,在 cmets 中注明,但如果你需要这种类型的东西,请随意剪切和粘贴。我保证不会叫你懒惰:

- (void)makeAnImageFlyFrom:(UIImageView *)imageViewA to:(UIImageView *)imageViewB duration:(NSTimeInterval)duration {

    // it's simpler but less general to not pass in the path.  i chose simpler because
    // there's a lot of geometry work using the imageView frames here anyway.

    UIImageView *animationView = [[UIImageView alloc] initWithImage:imageViewA.image];
    animationView.tag = kANIMATION_IMAGE_TAG;
    animationView.frame = imageViewA.frame;
    [self addSubview:animationView];

    // scale
    CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
    [resizeAnimation setFromValue:[NSValue valueWithCGSize:imageViewA.bounds.size]];
    [resizeAnimation setToValue:[NSValue valueWithCGSize:imageViewB.bounds.size]];

    // build the path
    CGRect aRect = [imageViewA convertRect:imageViewA.bounds toView:self];
    CGRect bRect = [imageViewB convertRect:imageViewB.bounds toView:self];

    // unclear why i'm doing this, but the rects converted to this view's
    // coordinate system seemed have origin's offset negatively by half their size
    CGFloat startX = aRect.origin.x + aRect.size.width / 2.0;
    CGFloat startY = aRect.origin.y + aRect.size.height / 2.0;
    CGFloat endX = bRect.origin.x + bRect.size.width / 2.0;
    CGFloat endY = bRect.origin.y + bRect.size.height / 2.0;

    CGFloat deltaX = endX - startX;
    CGFloat deltaY = endY - startY;

    // these control points suited the path i needed.  your results may vary
    CGFloat cp0X = startX + 0.3*deltaX;
    CGFloat cp0Y = startY - 1.3*deltaY;
    CGFloat cp1X = endX + 0.1*deltaX;
    CGFloat cp1Y = endY - 0.5*deltaY;

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, startX, startY);
    CGPathAddCurveToPoint(path, NULL, cp0X, cp0Y, cp1X, cp1Y, endX, endY);

    // keyframe animation
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    keyframeAnimation.calculationMode = kCAAnimationPaced;
    keyframeAnimation.fillMode = kCAFillModeForwards;
    keyframeAnimation.removedOnCompletion = NO;
    keyframeAnimation.path = path;

    // assuming i need to manually release, despite ARC, but not sure
    CGPathRelease(path);

    // a little unclear about the fillMode, but it works
    // also unclear about removeOnCompletion, because I remove the animationView
    // but that seems to be insufficient
    CAAnimationGroup *group = [CAAnimationGroup animation]; 
    group.fillMode = kCAFillModeForwards;
    group.removedOnCompletion = NO;
    [group setAnimations:[NSArray arrayWithObjects:keyframeAnimation, resizeAnimation, nil]];
    group.duration = duration;
    group.delegate = self;

    // unclear about what i'm naming with the keys here, and why
    [group setValue:animationView forKey:@"animationView"];

    [animationView.layer addAnimation:group forKey:@"animationGroup"];
}

// clean up after like this

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
    UIImageView *imageViewForAnimation = (UIImageView *)[self viewWithTag:kANIMATION_IMAGE_TAG];
    // get the imageView passed to the animation as the destination
    UIImageView *imageViewB = (UIImageView *)[self viewWithTag:kDEST_TAG];

    imageViewB.image = imageViewForAnimation.image;
    [imageViewForAnimation removeFromSuperview];
}

【讨论】:

  • 天哪!真的很有帮助的家伙..谁告诉你是懒惰的!..只是 1 混乱..你在哪里添加 kDEST_TAG?
  • 谢谢。它只是一个 int 标签的#define。将其分配给您希望图像飞行的图像视图:#define kDEST_TAG 128 然后 imageViewDestination.tag = kDEST_TAG。
  • 从那时起我对这段代码进行了一些改进。让我知道您是否需要帮助或变体,我会提供。
  • 这是我的最新资料pastebin.com/FZXvRDS2。新界面允许您指定一个矩形目标(而不是 imageView)和一个在完成时调用的块。然后,在块中,您可以将图像分配给另一个 UIImageView,或者做任何您想做的事情。它还可以更好地计算动画的路径。
  • @MilKyWaY - 我不得不从我的项目中调整该代码以使其对您更通用。这导致我犯了一个错误。在该粘贴箱中的第 10 行之前,添加行 self.animationParent = parent;
猜你喜欢
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 2012-04-21
  • 1970-01-01
相关资源
最近更新 更多