类似nike+、香蕉打卡的转场动画效果-b
首先,支持并感谢@wazrx 的 http://www.jianshu.com/p/45434f73019e和@onevcat 的https://onevcat.com/2013/10/vc-transition-in-ios7/ 对于转场动画的讲解和实现,非常详细,本人也是看过他们的文章后受的启发,快速实现了基于本项目需求的转场动画效果。
效果如下:(gif是我们的美术大师帮忙做的演示动效,实际的效果要比这个好,可通过文章最后链接下载我们的app:柠檬跑步,查看效果)
地图切换.gif
我的需求是两个页面push、pop之间的切换,所以自定义了push的转场动画,首先需要个遵循<UIViewControllerAnimatedTransitioning>协议的管理对象,并实现其两个方法:
XWCircleSpreadTransition.h
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, XWCircleSpreadTransitionType) {
XWCircleSpreadTransitionTypePush = 0,
XWCircleSpreadTransitionTypePop
};
@interface XWCircleSpreadTransition : NSObject<UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) XWCircleSpreadTransitionType type;
+ (instancetype)transitionWithTransitionType:(XWCircleSpreadTransitionType)type;
- (instancetype)initWithTransitionType:(XWCircleSpreadTransitionType)type;@end
XWCircleSpreadTransition.m
#import "XWCircleSpreadTransition.h"
@implementation XWCircleSpreadTransition
+ (instancetype)transitionWithTransitionType:(XWCircleSpreadTransitionType)type{
return [[self alloc] initWithTransitionType:type];
}
- (instancetype)initWithTransitionType:(XWCircleSpreadTransitionType)type{
self = [super init];
if (self) {
_type = type;
}
return self;
}
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 0.7;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
switch (_type) {
case XWCircleSpreadTransitionTypePush:
[self presentAnimation:transitionContext];
break;
case XWCircleSpreadTransitionTypePop:
[self dismissAnimation:transitionContext];
break;
}
}
- (void)dismissAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *containerView = [transitionContext containerView];
[containerView insertSubview:toVC.view atIndex:0]; //画两个圆路径
CGFloat radius = sqrtf(containerView.frame.size.height * containerView.frame.size.height + containerView.frame.size.width * containerView.frame.size.width) / 2; UIBezierPath *startCycle = [UIBezierPath bezierPathWithArcCenter:containerView.center radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:YES];// UIBezierPath *endCycle = [UIBezierPath bezierPathWithOvalInRect:temp.mapBtnFrame];
UIBezierPath *endCycle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 0, 0)]; //创建CAShapeLayer进行遮盖
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.fillColor = [UIColor greenColor].CGColor;
maskLayer.path = endCycle.CGPath;
fromVC.view.layer.mask = maskLayer; //创建路径动画
CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
maskLayerAnimation.delegate = self;
maskLayerAnimation.fromValue = (__bridge id)(startCycle.CGPath);
maskLayerAnimation.toValue = (__bridge id)((endCycle.CGPath));
maskLayerAnimation.duration = [self transitionDuration:transitionContext];
maskLayerAnimation.delegate = self;
maskLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[maskLayerAnimation setValue:transitionContext forKey:@"transitionContext"];
[maskLayer addAnimation:maskLayerAnimation forKey:@"path"];
}
- (void)presentAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{ UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *containerView = [transitionContext containerView];
[containerView addSubview:toVC.view]; //画两个圆路径// UIBezierPath *startCycle = [UIBezierPath bezierPathWithOvalInRect:fromVC.mapBtnFrame];
UIBezierPath *startCycle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 0, 0)]; CGFloat x = MAX(100, containerView.frame.size.width - 100); CGFloat y = MAX(100, containerView.frame.size.height - 100); CGFloat radius = sqrtf(pow(x, 2) + pow(y, 2)); UIBezierPath *endCycle = [UIBezierPath bezierPathWithArcCenter:containerView.center radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:YES]; //创建CAShapeLayer进行遮盖
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = endCycle.CGPath; //将maskLayer作为toVC.View的遮盖
toVC.view.layer.mask = maskLayer; //创建路径动画
CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
maskLayerAnimation.delegate = self; //动画是加到layer上的,所以必须为CGPath,再将CGPath桥接为OC对象
maskLayerAnimation.fromValue = (__bridge id)(startCycle.CGPath);
maskLayerAnimation.toValue = (__bridge id)((endCycle.CGPath));
maskLayerAnimation.duration = [self transitionDuration:transitionContext];
maskLayerAnimation.delegate = self;
maskLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[maskLayerAnimation setValue:transitionContext forKey:@"transitionContext"];
[maskLayer addAnimation:maskLayerAnimation forKey:@"path"];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
switch (_type) {
case XWCircleSpreadTransitionTypePush:{
id<UIViewControllerContextTransitioning> transitionContext = [anim valueForKey:@"transitionContext"]; [transitionContext completeTransition:YES];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
toView.layer.mask = nil;
UIViewController *vc = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; vc.view.layer.mask = nil; }
break;
case XWCircleSpreadTransitionTypePop:{
id<UIViewControllerContextTransitioning> transitionContext = [anim valueForKey:@"transitionContext"];
[transitionContext completeTransition:YES];
UIViewController *vc = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
vc.view.layer.mask = nil; }
break;
}
}
@end
剩下的就是在ViewControllerA中实现代理<UINavigationControllerDelegate>中的animationControllerForOperation:
#pragma mark -
#pragma mark - UINavigation Delegate
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
if (fromVC == self) {
return [XWCircleSpreadTransition transitionWithTransitionType:XWCircleSpreadTransitionTypePush];
}
if (toVC == self) {
return [XWCircleSpreadTransition transitionWithTransitionType:XWCircleSpreadTransitionTypePop];
}
return nil;
}
到此,这个简单的转场动画已经实现完毕,而且动画效果可以自定义成自己想要的展现形式。
类似nike+、香蕉打卡的转场动画效果-b的更多相关文章
- iOS CATransition 自定义转场动画
https://www.jianshu.com/p/39c051cfe7dd CATransition CATransition 是CAAnimation的子类(如下图所示),用于控制器和控制器之间的 ...
- iOS 动画学习之视图控制器转场动画
一.概述 1.系统会创建一个转场相关的上下文对象,传递到动画执行器的animateTransition:和transitionDuration:方法,同样,也会传递到交互Controller的star ...
- 自己定义转场动画--Swift3.0版本号
转场动画这事.说简单也简单.能够通过presentViewController:animated:completion:和dismissViewControllerAnimated:completio ...
- ios基础动画、关键帧动画、动画组、转场动画等
概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画.关键帧动画 ...
- iOS自定义转场动画实战讲解
iOS自定义转场动画实战讲解 转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerA ...
- 超酷炫的转场动画?CSS 轻松拿下!
在 WeGame 的 PC 端官网首页,有着非常多制作精良的基于滚动的动画效果. 这里我简单截取其中 2 个比较有意思的转场动画,大家感受感受.转场动画 1: 转场动画 2: 是不是挺有意思的,整个动 ...
- iOS开发UI篇—核心动画(转场动画和组动画)
转自:http://www.cnblogs.com/wendingding/p/3801454.html iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的 ...
- CATransition-转场动画
CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CATrans ...
- iOS:核心动画之转场动画CATransition
转场动画——CATransition CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 U ...
随机推荐
- Networking - ICMP 协议
发送到远程计算机的数据通常发经过一个或多个路由器,这些路由器在把数据传输到最终目的地的过程中可能发生多种问题.路由器利用 ICMP 把问题通知给源 IP.ICMP 还有用于其他调试和排错的功能. IC ...
- over Oracle
QL code: sql over的作用及用法RANK ( ) OVER ( [query_partition_clause] order_by_clause )DENSE_RANK ( ) OVER ...
- C++转到C#历程零基础知识(持续增加)
1.命名空间.类和源文件的关系:几个源文件用同一个命名空间时候,那么这几个源文件中的各个类之间的调用时可行的.他不会根据你的源文件分离而分开,因为最终编译后生成的是dll,这里来看你的几个源文件是没有 ...
- (转)19个必须知道的Visual Studio快捷键
本文将为大家列出在 Visual Studio 中常用的快捷键,正确熟练地使用快捷键,将大大提高你的编程工作效率. 项目相关的快捷键 Ctrl + Shift + B = 生成项目 Ctrl + Al ...
- Electron(一)--初步了解并动手HelloWorld
现在需要做一个桌面应用,心里有点不甘,因为想做出一个简单的客户端,你要么使用Java的Swing编程,要么会使用MFC等等,这样学习的代价太高,也不便维护,于是了解了一下Electron,Electr ...
- Android知识思维导图
注:图片来源于网络,谢谢分享. 一. 项目目录结构: 布局控件 ListVIew控件 Widget:(窗口小部件) Activity Manager 二. 应用程序的5个模块构成: Activit ...
- L001-老男孩教育-Python13期VIP视频-19节-pbb
L001-老男孩教育-Python13期VIP视频-19节-pbb Windows上安装 Python3开发环境 下载:www.python.org >选择Downloads>All re ...
- 锋利的jquery-validation
jquery插件 jquery插件项目托管于gitHub,项目地址https://github.com/jquery/plugins.jquery.com jquery插件的使用 表单验证插件 现在网 ...
- 一种C# TCP异步编程中遇到的问题
最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发. 程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,G ...
- 配置ADB 工具 (Win7_64)
ADB (Android Debut Bridge) ADB这个工具, 让我们可以用电脑来操纵手机 Android studio 安装好之后在SDK 中就有ADB 但是我们想使用它还需要配置它的环境变 ...