两个视图之间的自定义循环过渡

时间:2014-07-31 12:25:51

标签: ios quartz-core cabasicanimation

我想创建一个类似于动画的动画,用于在Spy Mouse应用程序中更改不同视图之间的动画。观看此视频以供参考:

http://www.youtube.com/watch?v=ylFdl7W3Srw

screenshot of the circular animation

我无法做同样的事情。我的动画显示的是矩形区域而不是圆形视图。

CABasicAnimation *cornerRadiusAction = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];    

cornerRadiusAction.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
cornerRadiusAction.duration = 5.0f;
cornerRadiusAction.toValue = [NSNumber numberWithFloat:self.view.bounds.size.height*2];
[self.view.layer addAnimation:cornerRadiusAction forKey:nil];

2 个答案:

答案 0 :(得分:7)

代码在行动。

enter image description here

解释。

仅仅设置cornerRadius的动画效果无法达到这样的效果。您需要使用CALayer的遮罩并修改圆形遮罩大小的动画。下面的代码可以满足您的需求。动画GIF显示了它的实际效果。

@property (weak, nonatomic) IBOutlet UIView *customView;

- (IBAction)buttonTapped:(id)sender
{
    // Set up the shape of the circle.
    CGFloat maskDiameter = sqrtf(powf(CGRectGetWidth(_customView.bounds), 2)
                                 + powf(CGRectGetHeight(_customView.bounds), 2));

    CAShapeLayer *mask = [CAShapeLayer layer];

    // Make a circular shape.
    mask.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0f,
                                                                   0.0f,
                                                                   maskDiameter,
                                                                   maskDiameter)
                                           cornerRadius:maskDiameter/2.0f].CGPath;
    // Center the shape in the view.
    mask.position = CGPointMake((CGRectGetWidth(_customView.bounds) - maskDiameter)/2,
                                (CGRectGetHeight(_customView.bounds) - maskDiameter)/2);

    // Fill the circle.
    mask.fillColor = [UIColor blackColor].CGColor;

    // Add as a mask to the parent layer
    _customView.layer.mask = mask;

    // Animate.
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
    animation.duration = 5.0f;
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = NO;

    // Create new path.
    CGPathRef newPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(maskDiameter/2.0f,
                                                                           maskDiameter/2.0f,
                                                                           0.0f,
                                                                           0.0f)
                                                   cornerRadius:0.0f].CGPath;
    // Set start and end values.
    animation.fromValue = (id)mask.path;
    animation.toValue = (__bridge id)newPath;

    // Start the animaiton.
    [mask addAnimation:animation forKey:@"path"];

}

答案 1 :(得分:2)

这是 Swift 中的@RaffAI's answer作为您可以使用任何所需视图调用的函数:

func circleAnim(_ view: UIView, duration: CFTimeInterval) {
    let maskDiameter = CGFloat(sqrtf(powf(Float(view.bounds.width), 2) + powf(Float(view.bounds.height), 2)))
    let mask = CAShapeLayer()
    let animationId = "path"

    // Make a circular shape.
    mask.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: maskDiameter, height: maskDiameter), cornerRadius: maskDiameter / 2).cgPath

    // Center the shape in the view.
    mask.position = CGPoint(x: (view.bounds.width - maskDiameter) / 2, y: (view.bounds.height - maskDiameter) / 2)

    // Fill the circle.
    mask.fillColor = UIColor.black.cgColor

    // Add as a mask to the parent layer.
    view.layer.mask = mask

    // Animate.
    let animation = CABasicAnimation(keyPath: animationId)
    animation.duration = duration
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false

    // Create a new path.
    let newPath = UIBezierPath(roundedRect: CGRect(x: maskDiameter / 2, y: maskDiameter / 2, width: 0, height: 0), cornerRadius: 0).cgPath

    // Set start and end values.
    animation.fromValue = mask.path
    animation.toValue = newPath

    // Start the animaiton.
    mask.add(animation, forKey: animationId)
}