【问题标题】:Custom circular transition between two views两个视图之间的自定义圆形过渡
【发布时间】:2014-07-31 12:25:50
【问题描述】:

我想创建一个类似于动画的动画,用于在 Spy Mouse 应用程序中的不同视图之间进行切换。请参阅此视频以供参考:

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

我不能这样做。我的动画显示了一个矩形区域而不是圆形视图。

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

【问题讨论】:

    标签: ios quartz-core cabasicanimation


    【解决方案1】:

    实际代码。

    解释。

    您无法简单地为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"];
    
    }
    

    【讨论】:

    • 非常感谢 reecon
    • 嘿,我想在两个视图之间切换时使用相同的效果,因为我从下一个视图提供了掩码内容,mask.contents = (id)[[self getImageFromNextView] CGImage];但它只是显示类似于您的 gif,首先它使用类似于您的黑色删除视图,然后添加下一个视图,但我希望它只是隐藏上面的视图,以便可以轻松看到后视图。
    • 我会将第二个视图(您要显示的那个)放在您要隐藏的视图下方。就我而言,您在 gif 中看到的黑色区域只是一个空视图。不要在掩码内容中添加东西。仅用于为视图的消失设置动画。
    【解决方案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 = .forwards
        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 animation.
        mask.add(animation, forKey: animationId)
    }
    

    【讨论】:

      猜你喜欢
      • 2012-03-20
      • 1970-01-01
      • 2017-02-10
      • 2013-01-28
      • 2014-09-02
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多