您正在更改掩码的bounds,而不是path。您确实需要更改mask 的path。从理论上讲,您可以使用 CABasicAnimation 做到这一点,但我个人发现在为路径设置动画时(尤其是蒙版的路径)非常不稳定。
如果可以的话,我会完全取消遮罩并设置 testView 的框架,使其不可见(例如高度为零),然后使用基于块的 @987654327 为该框架的变化设置动画@animateWithDuration。 (注意,如果使用自动布局,那么您可能会为更改了约束的setNeedsLayout 设置动画)。
如果您确实需要使用CAShapeLayer 掩码,您可以尝试在掩码CAShapeLayer 上的path 键的CABAsicAnimation 和animateWithKeyPath。
就个人而言,在为路径更改设置动画时,我会使用显示链接,例如类似:
- (IBAction)didTapButton:(UIBarButtonItem *)sender {
[AnimationDisplayLink animateWithDuration:3.0 animationHandler:^(CGFloat percent) {
self.mask.path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, self.testView.bounds.size.width, self.testView.bounds.size.height * percent)].CGPath;
} completionHandler:nil];
}
我的AnimationDisplayLink定义如下:
@interface AnimationDisplayLink : NSObject
@property (nonatomic) CGFloat animationDuration;
@property (nonatomic, copy) void(^animationHandler)(CGFloat percent);
@property (nonatomic, copy) void(^completionHandler)();
@end
@interface AnimationDisplayLink ()
@property (nonatomic) CFAbsoluteTime startTime;
@property (nonatomic, strong) CADisplayLink *displayLink;
@end
@implementation AnimationDisplayLink
+ (instancetype)animateWithDuration:(CGFloat)duration animationHandler:(void (^)(CGFloat percent))animationHandler completionHandler:(void (^)(void))completionHandler {
AnimationDisplayLink *handler = [[self alloc] init];
handler.animationDuration = duration;
handler.animationHandler = animationHandler;
handler.completionHandler = completionHandler;
[handler startAnimation];
return handler;
}
- (void)startAnimation {
self.startTime = CFAbsoluteTimeGetCurrent();
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)stopAnimation {
[self.displayLink invalidate];
self.displayLink = nil;
}
- (void)handleDisplayLink:(CADisplayLink *)displayLink {
CGFloat elapsed = CFAbsoluteTimeGetCurrent() - self.startTime;
CGFloat percent = elapsed / self.animationDuration;
if (percent >= 1.0) {
[self stopAnimation];
if (self.animationHandler) self.animationHandler(1.0);
if (self.completionHandler) self.completionHandler();
} else {
if (self.animationHandler) self.animationHandler(percent);
}
}
@end