且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

动画UIView过渡,如扩展点到圆圈

更新时间:2022-01-24 04:28:23

在我的情况下我做到了方式:

in my case I did it that way:

CAShapeLayer 实例设置为自定义视图子类的图层掩码属性

set a CAShapeLayer instance as the layer's mask property of your custom view subclass

@interface MyCustomView ()
@property (nonatomic, strong) CircleShapeLayer *circleShapeLayer;
@end

@implementation MyCustomView

- (id) initWithFrame: (CGRect) frame {
    self = [super initWithFrame: CGRectZero];
    if (self) {
        self.layer.mask = self.shapeLayer;
        [self.layer.mask setValue: @(0) forKeyPath: @"transform.scale"];
    }
    return self;
}

将此遮罩层缩放为fullsize。你的观点代码:

zoom this mask layer to fullsize. code of your view:

- (void) zoom {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath: @"transform.scale"];
    animation.fromValue = [self.layer.mask valueForKeyPath: @"transform.scale"];
    animation.toValue = @(1);
    animation.duration = 2.0;
    animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
    animation.delegate = self;
    // Important: change the actual layer property before installing the animation.
    [self.layer.mask setValue: animation.toValue forKeyPath: animation.keyPath];
    // Now install the explicit animation, overriding the implicit animation.
    [self.layer.mask addAnimation: animation forKey: animation.keyPath];
    return;
}

- (CAShapeLayer *) circleShapeLayer {
    if (!_ circleShapeLayer) {
        _circleShapeLayer = [SGMaskLayer layer];
        _circleShapeLayer.delegate = _shapeLayer;
        _circleShapeLayer.frame = self.bounds;
        _circleShapeLayer.needsDisplayOnBoundsChange = YES;
    }

    return _circleShapeLayer;
}

@end

掩码图层的代码:

@interface CircleShapeLayer : CAShapeLayer
@end

@implementation CircleShapeLayer

- (void) drawLayer: (CALayer *) layer inContext: (CGContextRef) ctx {
    UIGraphicsPushContext(ctx);
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect: self.bounds];
    self.path = circlePath.CGPath;
    UIGraphicsPopContext();
}

@end

来自文档:


图层的alpha通道决定了图层内容
和背景的显示量。完全或部分不透明像素允许
显示底层内容,但完全透明像素
阻止该内容。

The layer’s alpha channel determines how much of the layer’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through but fully transparent pixels block that content.

此属性的默认值为没有。配置
掩码时,请记住将掩码图层的大小和位置设置为
,确保它与掩码图层正确对齐。

The default value of this property is nil nil. When configuring a mask, remember to set the size and position of the mask layer to ensure it is aligned properly with the layer it masks.

所以我用UIBezierPath绘制了一个圆圈以实现圆形遮罩。在开始时我将蒙版的比例因子设置为0,因此视图的图层都不可见。然后比例因子被设置为1(填充图层的边界)动画,这给出了一个很好的圆形动画,增加了它从中心的半径。

so I drew a circle with UIBezierPath to achieve the round mask. at the beginning I set the mask's scale factor to 0 so nothing of the view's layer is visible. then the scale factor is set to 1 (filling the layer's bounds) animated which gives a nice animation of a circle increasing it's radius from the center.

你可能还需要一个动画移动视图的中心点。两个动画都可以包装在CAAnimationGroup中。

you might need one more animation shifting the center point of your view. both animations can be wrapped in a CAAnimationGroup.