1

我已经设法使用 [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;

}

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

4

1 回答 1

1

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

- (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];
}
于 2012-03-18T23:24:42.860 回答