マスクの変更をアニメーション化することができます。
マスク レイヤーとして CAShapeLayer を使用することを好みます。プロパティ パスを使用してマスクの変更をアニメーション化すると非常に便利です。
変更をアニメーション化する前に、ソースのコンテンツをインスタンス CGImageRef にダンプし、アニメーション用の新しいレイヤーを作成します。アニメーション中は元のレイヤーを非表示にし、アニメーションの終了時に表示します。
プロパティ パスにキー アニメーションを作成するサンプル コードを次に示します。独自のパス アニメーションを作成する場合は、パスに常に同じ数のポイントがあることを確認してください。
- (CALayer*)_mosaicMergeLayer:(CGRect)bounds content:(CGImageRef)content isUp:(BOOL)isUp {
CALayer* layer = [CALayer layer];
layer.frame = bounds;
layer.backgroundColor = [[UIColor clearColor] CGColor];
layer.contents = (id)content;
CAShapeLayer* maskLayer = [CAShapeLayer layer];
maskLayer.fillColor = [[UIColor blackColor] CGColor];
maskLayer.frame = bounds;
maskLayer.fillRule = kCAFillRuleEvenOdd;
maskLayer.path = ( isUp ? [self _maskArrowUp:-bounds.size.height*2] : [self _maskArrowDown:bounds.size.height*2] );
layer.mask = maskLayer;
CAKeyframeAnimation* ani = [CAKeyframeAnimation animationWithKeyPath:@"path"];
ani.removedOnCompletion = YES;
ani.duration = 0.3f;
ani.fillMode = kCAFillModeForwards;
ani.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
NSArray* values = ( isUp ?
[NSArray arrayWithObjects:
(id)[self _maskArrowUp:0],
(id)[self _maskArrowUp:-ceilf(bounds.size.height*1.2)],
nil]
:
[NSArray arrayWithObjects:
(id)[self _maskArrowDown:0],
(id)[self _maskArrowDown:bounds.size.height],
nil]
);
ani.values = values;
ani.delegate = self;
[maskLayer addAnimation:ani forKey:nil];
return layer;
}
- (void)_startMosaicMergeAni:(BOOL)up {
CALayer* overlayer = self.aniLayer;
CGRect bounds = overlayer.bounds;
self.firstHalfAni = NO;
CALayer* frontLayer = nil;
frontLayer = [self _mosaicMergeLayer:bounds
content:self.toViewSnapshot
isUp:up];
overlayer.contents = (id)self.fromViewSnapshot;
[overlayer addSublayer:frontLayer];
}