iOS实现类似格瓦拉电影的转场动画

2020-01-18 16:52:49王冬梅

移动完之后,要以圆形扩散显示出push之后的界面。就可以通过UIBezierPathCAShapeLayer来实现。UIBezierPath表示路径,CAShapeLayer可以根据路径来显示区域,那么我们可以以第一个界面的视图先看看效果。


 UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.collectionView.bounds];

 [path appendPath:[UIBezierPath bezierPathWithArcCenter:self.collectionView.center radius:50 startAngle:0 endAngle:2*M_PI clockwise:NO]];

 CAShapeLayer *layer = [CAShapeLayer layer];
 layer.path = path.CGPath;
 self.collectionView.layer.mask = layer;

初始化path路径以collectionView的四边画一个路径,然后加入一个以collectionView的中心为圆点,半径为50的路径,显示的区域就为两个路径之间的区域。

ios,格瓦拉动画效果,转场动画,push转场动画

然后再把代码中的radius大小设为200

ios,格瓦拉动画效果,转场动画,push转场动画

现在,我们创建一个CABasicAnimation对象去完成扩散的动画,起始位置是半径为10的圆,终点位置是半径为200的圆.


 UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.collectionView.bounds];

 [path appendPath:[UIBezierPath bezierPathWithArcCenter:self.collectionView.center radius:10 startAngle:0 endAngle:2*M_PI clockwise:NO]];

 UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:self.collectionView.bounds];

 [path2 appendPath:[UIBezierPath bezierPathWithArcCenter:self.collectionView.center radius:200 startAngle:0 endAngle:2*M_PI clockwise:NO]];

 CAShapeLayer *layer = [CAShapeLayer layer];
 self.collectionView.layer.mask = layer;

 CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
 pathAnimation.fromValue = (__bridge id)path.CGPath;
 pathAnimation.toValue = (__bridge id)path2.CGPath;
 pathAnimation.duration = 1.0;
 pathAnimation.repeatCount = 1;
 pathAnimation.removedOnCompletion = NO;
 pathAnimation.fillMode = kCAFillModeForwards;
 pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
 [layer addAnimation:pathAnimation forKey:@"pathAnimate"];

ios,格瓦拉动画效果,转场动画,push转场动画

现在就可以完成push的 转场效果了。注意圆圈白色部分显示的是collectionView底部的self.view的视图。


//加入收合动画
- (void)addPathAnimateWithView:(UIView *)toView fromPoint:(CGPoint)point{
 //create path
 UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, k_SF_SCREEN_WIDTH, k_SF_SCREEN_HIGHT)];
 //create path
 [path appendPath:[UIBezierPath bezierPathWithArcCenter:point radius:0.1 startAngle:0 endAngle:2*M_PI clockwise:NO]];

 CGFloat radius = point.y > 0?k_SF_SCREEN_HIGHT*3/4: k_SF_SCREEN_HIGHT*3/4-point.y;
 UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, k_SF_SCREEN_WIDTH, k_SF_SCREEN_HIGHT)];
 [path2 appendPath:[UIBezierPath bezierPathWithArcCenter:point radius:radius startAngle:0 endAngle:2*M_PI clockwise:NO]];

 CAShapeLayer *shapeLayer = [CAShapeLayer layer];
 //shapeLayer.path = path.CGPath;
 toView.layer.mask = shapeLayer;

 CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
 pathAnimation.fromValue = _type == animate_push? (__bridge id)path.CGPath:(__bridge id)path2.CGPath;
 pathAnimation.toValue = _type == animate_push? (__bridge id)path2.CGPath:(__bridge id)path.CGPath;
 pathAnimation.duration = _duration/3;
 pathAnimation.repeatCount = 1;
 pathAnimation.removedOnCompletion = NO;
 pathAnimation.fillMode = kCAFillModeForwards;
 pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
 [shapeLayer addAnimation:pathAnimation forKey:@"pathAnimate"];
}