必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

目标控制器视图从下向上弹出必威:,//根据一个

2019-09-17 13:21 来源:未知
1、

首先, 我们先创建一个动画管理类,继承NSObject并遵循UIViewControllerAnimatedTransitioning还有CAAnimationDelegate协议(CAAnimationDelegate这个协议是因为用圆缩放动画时候需要用到),我是将presentdismiss的动画管理类分开写的,就以present动画为例,我创建了CustomPresentAnimation类。在这个类中,我使用了两种动画,因而我创建了一个枚举用来标示:

enum AnimationType { case circle //圆缩放 case rectangle //矩形偏移}

首先  UIBezierPath创建方法介绍


参考官方API

必威 1

1、+ (instancetype)bezierPathWithRect:(CGRect)rect;

   这个工厂方法根据一个矩形画贝塞尔曲线。

2、+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;

这个工厂方法根据一个矩形画内切曲线。通常用它来画圆或者椭圆。

3、+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect

cornerRadius:(CGFloat)cornerRadius;

画矩形,但是这个矩形是可以画圆角的。第一个参数是矩形,第二个参数是圆角大小。

4、+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect

byRoundingCorners:(UIRectCorner)corners

cornerRadii:(CGSize)cornerRadii;

次与第3个 工厂方法功能是一样的,但是可以指定某一个角画成圆角。像这种我们就可以很容易地给UIView扩展添加圆角的方法了。

5、+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

这个工厂方法用于画弧,参数说明如下:

center: 弧线中心点的坐标

radius: 弧线所在圆的半径

startAngle: 弧线开始的角度值

endAngle: 弧线结束的角度值

clockwise: 是否顺时针画弧线

必威 2

path.lineCapStyle=kCGLineCapRound;

[fillColor set]; 

前言

我们经常在没有 UINavigationController的时候,这里我们先说这种情况。使用presentdismisspresent modally弹出模态控制器)的方式切换控制器视图,默认情况下,目标控制器视图从下向上弹出。系统有ViewController自带的modalTransitionStyle属性,可以修改ViewController弹出和消失时的动画。如:

func nextClick() -> Void { second.modalTransitionStyle = .partialCurl self.present(second, animated: true, completion: nil) }

系统自带的有四种动画:

public enum UIModalTransitionStyle : Int { case coverVertical // 默认 底部滑入 case flipHorizontal //水平翻转 case crossDissolve //渐隐 @available(iOS 3.2, *) case partialCurl //翻页}

但是有时候呢,系统自带的转场动画并不能满足我们的需求,因为我们需要自定义动画。

其实呢,在转场的过程中系统会提供一个视图容器用来盛装进行跳转控制器的视图,如下图所示,当前的FirstViewControllerpresent到SecondViewController的时候,此时,FirstViewControllerview变成fromView,这个视图会自动加入到transtition container view中,然后在跳转过程中我们需要做的就是将SecondViewController的视图(此时是toView)加入到这个容器中,然后为这个toView的展现增加动画。

必威 3PresentPic.png

基础知识[参考原创]


使用UIBezierPath可以创建基于矢量的路径,此类是Core Graphics框架关于路径的封装。使用此类可以定义简单的形状,如椭圆、矩形或者有多个直线和曲线段组成的形状等。

UIBezierPath是CGPathRef数据类型的封装。如果是基于矢量形状的路径,都用直线和曲线去创建。我们使用直线段去创建矩形和多边形,使用曲线去创建圆弧(arc)、圆或者其他复杂的曲线形状。

  • (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
    参数:
    center:弧线中心点的坐标
    radius:弧线所在圆的半径
    startAngle:弧线开始的角度值
    endAngle:弧线结束的角度值
    clockwise:是否顺时针画弧线

必威 4

其中第一个参数一样是传了个矩形,第二个参数是指定在哪个方向画圆角,第三个参数是一个CGSize类型,用来指定水平和垂直方向的半径的大小。看下效果图:

小结:

以上就是关于presentdismiss的自定义转场动画比较详细的用法和navigationCotrollerpushpop的自定义转场动画的简单用法介绍。如果有不同见解,欢迎留言交流。

接下来开始 一些实例。

//以三个点画一段曲线,一般和moveToPoint配合使用

这个使用比较多,因为这个工厂方法创建的对象,我们可以根据我们的需要任意定制样式,可以画任何我们想画的图形。

path.lineCapStyle= kCGLineCapRound;

2、

UIViewControllerAnimatedTransitioning这个协议中有个方法:

public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval

这个方法是用来控制转场动画执行时间的。

我们的主要操作是在这个方法中进行的:

public func animateTransition(using transitionContext: UIViewControllerContextTransitioning)

在这个方法中,我们开始进行自定义Animation:先说矩形偏移的方法,效果如图:

必威 5rectangle.gif代码里面都有注释,比较容易理解。

// 修改过渡时的背景颜色 transitionContext.containerView.backgroundColor = UIColor.white // 得到toViewController let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)! // 得到fromViewController let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)! // 将toViewController.view 放到fromViewController.view之上 transitionContext.containerView.insertSubview(toViewController.view, aboveSubview: fromViewController.view) // 对toViewController.view 进行动画操作 toViewController.view.transform = CGAffineTransform(translationX: LGJWidth, y: LGJHeight) UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: { toViewController.view.transform = CGAffineTransform.identity fromViewController.view.transform = CGAffineTransform(translationX: -LGJWidth, y: -LGJHeight) }, completion: { (completion) in // 转场完成后 transitionWasCancelled fromViewController.view.transform = CGAffineTransform.identity transitionContext.completeTransition(!transitionContext.transitionWasCancelled) })

这个圆缩放的效果就比较常见了,效果如图:

必威 6circle.gif

这个效果主要是用在登录界面的转场中,思路如下:

第一步:找到fromViewtoView并且将toView放到containerView中。

let toVC: UIViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)! let containerView: UIView = transitionContext.containerView containerView.addSubview(toVC.view)

第二步:绘制圆这里用到贝塞尔曲线绘图,我有写过一篇关于贝塞尔曲线的简单使用方法的介绍,链接: startCircle: UIBezierPath = UIBezierPath(ovalIn: CGRect(x: LGJWidth/2, y: LGJHeight/2, width: 50, height: 50))这里用的是UIBezierPathpublic convenience init(ovalIn rect: CGRect)这个方法,这个方法是用来在给定的rect中绘制内切圆的,这里给的rect以当前view的中点为圆心,并且width=height,所以可以绘制出圆。第二个圆就是放大之后的圆,这里使用UIBezierPathinit(arcCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)这个方法,创建,使用这个方法我们要用到圆的radius半径、startAngle起始角度、endAngle终点角度,clockwise是否是顺时针画圆,这里我们需要的圆的半径通过勾股定理算出。利用CAShapeLayertoView的mask蒙版设为endCircle.cgPath`结束时的圆。

//画圆 let startCircle: UIBezierPath = UIBezierPath(ovalIn: CGRect(x: LGJWidth/2, y: LGJHeight/2, width: 50, height: 50)) let x: CGFloat = LGJWidth/2 let y: CGFloat = LGJHeight/2 //求出半径 pow a的x次方 let radius: CGFloat = sqrt + pow let endCircle: UIBezierPath = UIBezierPath(arcCenter: containerView.center, radius: radius, startAngle: 0, endAngle: CGFloat, clockwise: true) let maskLayer: CAShapeLayer = CAShapeLayer() maskLayer.path = endCircle.cgPath toVC.view.layer.mask = maskLayer

第三步:添加动画创建基础动画对象,设置动画的fromValuetoValue这里的这两个值也就是我们上一步用贝塞尔曲线画的两个路径。duration设置动画时间,timingFunction控制动画节奏,setValue添加动画的时候设置key,在代理方法中通过key获取animate,为了观察动画什么时候结束,我们将animation的代理设为self这就是为什么我们将这个类继承CAAnimationDelegate了,最后将动画添加到maskLayer,动画执行过程就是我们看见的从小圆变大的过程了。

let maskLayerAnimation: CABasicAnimation = CABasicAnimation() maskLayerAnimation.fromValue = startCircle.cgPath maskLayerAnimation.toValue = endCircle.cgPath maskLayerAnimation.duration = transitionDuration(using: transitionContext) maskLayerAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) maskLayerAnimation.setValue(transitionContext, forKey: "transitionContext") maskLayerAnimation.delegate = self maskLayer.add(maskLayerAnimation, forKey: "path")

第四步:结束跳转根据animation的代理方法,观察到动画完成后,根据animationkey找到transitionContext,结束动画,将toViewmask设为nil

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if type == .circle { let transitionContext: UIViewControllerContextTransitioning = anim.value(forKey: "transitionContext") as! UIViewControllerContextTransitioning transitionContext.completeTransition transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)?.view.layer.mask = nil } }

在所谓的fromViewController中,遵循UIViewControllerTransitioningDelegate协议。将toViewControllertransitioningDelegate设为自身。然后执行UIViewControllerTransitioningDelegate方法,presentA.type默认为circle

//MARK: -UIViewControllerTransitioningDelegate func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { let presentA = CustomPresentAnimation() presentA.type = .rectangle return presentA }

上面我们介绍了没有 UINavigationController的情况下模态跳转,接下来就简单说一下关于UINavigationController的转场动画的使用方法,其实管理动画的类都是一样的,唯一的不同就是在Controller里面的使用方法的不同,FirstViewController是第一个控制器,SecondViewController是第二个控制器,在第一个控制器中使用时,首先遵循UINavigationControllerDelegate控制器协议,将navigationController?.delegate = self,然后实现ControllerDelegate的代理方法:

func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { print("(navigationController) (operation.rawValue)") if operation == .push { return CustomPresentAnimation() } if operation == .pop { return CustomDismissAnimation() } return nil }
  • (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius

// 最后的闭合线是可以通过调用closePath方法来自动生成的,也可以调用-addLineToPoint:方法来添加

[path stroke];

  • (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect

controlPoint:控制点,对于二次贝塞尔曲线,只有一个控制点

画三次贝塞尔曲线

//以某个中心点画弧线

[strokeColorset];

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center                                  radius:(CGFloat)radius startAngle:(CGFloat)startAngle                             endAngle:(CGFloat)endAngle  clockwise:(BOOL)clockwise;

分类: IOS相关

看效果图:

image

//根据一个矩形画曲线

path.lineCapStyle=kCGLineCapRound;

[path stroke];

UIBezierPath贝塞尔弧线常用方法记
(2012-09-19 21:34:56)

UIBezierPath*path=[UIBezierPathbezierPath];

- (void)drawRoundedRectPath {

  • (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
    参数:
    corners:枚举值,可以选择某个角
    cornerRadii:圆角的大小

其中,第一个是默认的表示斜接,第二个是圆滑衔接,第三个是斜角连接。

// 设置填充颜色

//画二元曲线,一般和moveToPoint配合使用

[pathstroke];

- (void)drawThirdBezierPath

  • (UIBezierPath *)bezierPathWithRect:(CGRect)rect

[strokeColorset];

参数说明:

//根据矩形画带圆角的曲线

path.lineJoinStyle=kCGLineJoinRound;

UIColor*fillColor = [UIColorgreenColor];

//根据矩形框的内切圆画曲线

// 画矩形

UIColor*fillColor = [UIColorgreenColor];

参数:
endPoint:曲线的终点
controlPoint:画曲线的基准点

-(void)drawTrianglePath{

}

  • (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

// 设置填充颜色

[strokeColor set];  [path stroke];

//在矩形中,可以针对四角中的某个角加圆角

注意:要画圆,我们需要传的rect参数必须是正方形哦!

path.lineCapStyle= kCGLineCapRound;

参数:
endPoint:曲线的终点
controlPoint1:画曲线的第一个基准点
controlPoint2:画曲线的第二个基准点

[fillColorset];

lineCapStyle属性是用来设置线条拐角帽的样式的,其中有三个选择:

转载

UIBezierPath*path=[UIBezierPathbezierPath];

}

CGContextAddCurveToPoint()和
CGContextAddQuadCurveToPoint()两个函数

controlPoint:CGPointMake(self.frame.size.width/2,0)];

这个样式看起来很像sin或者cos函数吧?这两个只是特例而已,其实可以画任意图形,只是想不到,没有做不到的。

  • (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2

// 根据我们设置的各个点连线

如果要画只有一个角是圆角,那么我们就修改创建方法:

// 设置画笔颜色

第二个工厂方法功能是一样的,但是可以指定某一个角画成圆角。像这种我们就可以很容易地给UIView扩展添加圆角的方法了。

UIColor*strokeColor=[UIColorredColor];

四个都是圆角10:

path.lineWidth=1.5;

实现代码是这样的:

}

{// 传的是不是正方形,因此就可以绘制出椭圆圆了UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(20,20,self.frame.size.width-80,self.frame.size.height-40)];// 设置填充颜色UIColor*fillColor = [UIColorgreenColor];

[strokeColorset];

}

// 传的是正方形,因此就可以绘制出圆了

image

+(instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

// 设置画笔颜色

[pathclosePath];

center: 弧线中心点的坐标

先看效果图:

path.lineJoinStyle= kCGLineJoinRound; 

path.lineWidth=5.0;

先来学习一下关于控制点,如下图(图片来自网络):

提示:其组成是起始端点+控制点1+控制点2+终止端点

如下方法就是画三次贝塞尔曲线的关键方法,以三个点画一段曲线,一般和-moveToPoint:配合使用。

+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius (CGFloat)cornerRadius;

image

[pathaddQuadCurveToPoint:CGPointMake(self.frame.size.width-20,self.frame.size.height-100)

调用-moveToPoint:设置初始线段的起点

+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;

UIBezierPath*path = [UIBezierPathbezierPathWithRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40)]; 

+(instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

必威 7

改变UIBezierPath对象跟绘图相关的属性。如,我们可以设置画笔的属性、填充样式等

path.lineJoinStyle= kCGLineJoinRound;

[fillColorset];

[path fill];

看下效果图:

使用UIBezierPath画图步骤:

[pathaddCurveToPoint:CGPointMake(300,150)

提示:其组成是起始端点+控制点1+控制点2+终止端点

[pathaddLineToPoint:CGPointMake(self.frame.size.width/2,self.frame.size.height-20)];

}

其中第一个参数一样是传了个矩形,第二个参数是指定在哪个方向画圆角,第三个参数是一个CGSize类型,用来指定水平和垂直方向的半径的大小。看下效果图:

贝塞尔曲线必定通过首尾两个点,称为端点;中间两个点虽然未必要通过,但却起到牵制曲线形状路径的作用,称作控制点。关于三次贝塞尔曲线的控制器,看下图:

// 传的是不是正方形,因此就可以绘制出椭圆圆了

画二次贝塞尔曲线的步骤:

// 根据我们设置的各个点连线

必威 8

// 设置填充颜色

我们设置画笔颜色通过set方法:

-(void)drawThirdBezierPath{

UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.width-40)];

UIBezierPath*path=[UIBezierPathbezierPathWithRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40)];

[path fill];

如果要画只有一个角是圆角,那么我们就修改创建方法:

[path addLineToPoint:CGPointMake(self.frame.size.width/2,self.frame.size.height-20)];

TAG标签:
版权声明:本文由必威发布于必威-编程,转载请注明出处:目标控制器视图从下向上弹出必威:,//根据一个