参考:https://www.jianshu.com/p/e983b26fc011
2.UIView的动画;
let v1:UIView=UIView.init()
let v2:UIView=UIView.init()
UIView.transition(from: v1, to: v2, duration: 3, options: UIViewAnimationOptions.allowAnimatedContent) { (ist) in
}
UIView.animate(withDuration: 3) {
}
UIView.animateKeyframes(withDuration: 3, delay: 0, options: UIViewKeyframeAnimationOptions, animations: {
}) { (ist) in
}
UIView.animate(withDuration: 3, delay: 0, options: UIViewAnimationOptions.allowAnimatedContent, animations: {
}, completion: { (ist) in
})
===========================
3.UIImageview动画;
===============================
4.核心动画继承自CAAnimation,包括和CAPropertyAnimation(属性动画)和CAAnimationGroup(组动画)和CATransition(转场动画);
CAPropertyAnimation包括:CAKeyframeAnimation(帧动画)和CABasicAnimation;
CABasicAnimation包含CASpringAnimation
*****************CABasicAnimation
/**
基础动画:可以平移,旋转,缩放
*/
import UIKit
class LYBBasicAnimateVC: UIViewController,CAAnimationDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// basicAnimate()
keyFrameAnimate()
}
//基础动画
func basicAnimate(){
//手工创建layer
let redLayer:CALayer=CALayer.init()
//设置背景颜色
redLayer.backgroundColor = UIColor.red.cgColor
//设置大小和位置
redLayer.position = CGPoint.init(x: 100, y: 100)
redLayer.bounds = CGRect.init(x: 0, y: 0, width: 100, height: 100)
view.layer.addSublayer(redLayer)
//基本动画--旋转
//1.创建动画对象
let basic:CABasicAnimation=CABasicAnimation.init()
//2.设置属性 (默认绕着z轴旋转)
// fromValue--------------起始值;
// toValue----------------移动到多少;
// byValue---------------- 移动了多少
basic.keyPath = "transform.rotation";
//设置开始、结束值
basic.fromValue=0.1
basic.toValue = 0.5
//**缩放
basic.keyPath="transform.scale"
basic.byValue=0.65
//**
basic.keyPath="position"//或者 basic.keyPath="transform.translation"
basic.fromValue=NSValue.init(cgPoint: CGPoint.init(x: 0, y: 10))
basic.toValue=NSValue.init(cgPoint: CGPoint.init(x: 10, y: 10))
//2.2 设置动画时间
basic.duration = 2
basic.repeatCount=5//重复5次
basic.repeatDuration=1//
//设置代理(隐式代理)
basic.delegate=self
//设置动画结束后保持当前状态
basic.isRemovedOnCompletion=true
basic.fillMode = CAMediaTimingFillMode.forwards
//3.添加到要作用的layer上
redLayer.add(basic, forKey: nil)
}
//动画开始时间
func animationDidStart(_ anim: CAAnimation) {
}
//动画结束时间
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
}
// 关键帧动画
func keyFrameAnimate()
{
//手工创建layer
let redLayer:CALayer=CALayer.init()
//设置背景颜色
redLayer.backgroundColor = UIColor.red.cgColor
//设置大小和位置
redLayer.position = CGPoint.init(x: 100, y: 100)
redLayer.bounds = CGRect.init(x: 0, y: 0, width: 100, height: 100)
view.layer.addSublayer(redLayer)
//1.创建动画对象
let basic:CAKeyframeAnimation=CAKeyframeAnimation.init()
//2.设置属性 (默认绕着z轴旋转)
// fromValue--------------起始值;
// toValue----------------移动到多少;
// byValue---------------- 移动了多少
basic.keyPath = "transform.rotation";
//
// //**缩放
basic.keyPath="transform.scale"
//**
basic.keyPath="position"//
//帧的路径一,value和path只能选一个
let value1: NSValue = NSValue(cgPoint: CGPoint(x: 100, y: 100))
let value2: NSValue = NSValue(cgPoint: CGPoint(x: 200, y: 100))
let value3: NSValue = NSValue(cgPoint: CGPoint(x: 200, y: 200))
let value4: NSValue = NSValue(cgPoint: CGPoint(x: 100, y: 200))
let value5: NSValue = NSValue(cgPoint: CGPoint(x: 100, y: 300))
let value6: NSValue = NSValue(cgPoint: CGPoint(x: 200, y: 400))
basic.values = [value1, value2, value3, value4, value5, value6]
//创建路径对象(如果设置了path,value就被忽略了,path只对anchorpoint和position起作用)
// let path:UIBezierPath=UIBezierPath.init(ovalIn: CGRect.init(x: 20, y: 100, width: 300, height: 200))
// basic.path = path.cgPath;
//速度控制函数,控制动画的节奏
basic.timingFunction=CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
//2.2 设置动画时间
basic.duration = 2
basic.repeatCount=5//重复5次
basic.repeatDuration=1//
//设置代理(隐式代理)
basic.delegate=self
//设置动画结束后保持当前状态
basic.isRemovedOnCompletion=true
basic.fillMode = CAMediaTimingFillMode.forwards
//3.添加到要作用的layer上
redLayer.add(basic, forKey: nil)
}
}
************CAAnimationGroup组动画
//创建组动画
let animationGroup:CAAnimationGroup=CAAnimationGroup.init()
//3.把子动画添加到组动画中
animationGroup.animations = [basicAni,rotationAni,keyframeAni];
//设置组动画时间
animationGroup.duration = 5;
animationGroup.autoreverses =true;//动画完成后自动重新开始,默认为NO
//4.把组动画添加到要作用的layer上
redLayer.add(animationGroup, forKey: nil)
*************
=============
5.CATransaction(隐式动画)
非rootLayer,即手动创建的layer都包含隐式动画;(position,bounds,backgroundColor,)
CATransaction.begin()//开始动画
CATransaction.setAnimationDuration(CFTimeInterval.init(3))//设置动画时间
CATransaction.setDisableActions(true)//不显示动画
//改变layer的属性,属性的改变必须放在提交动画之前
CATransaction.commit()//提交动画
==============
6.CATransition(转场动画)
参考:https://www.jianshu.com/p/1f798a171e9a
/**
转场动画
核心动画继承自CAAnimation,包括和CAPropertyAnimation(属性动画)和CAAnimationGroup(组动画)和CATransition(转场动画);
CAPropertyAnimation包括:CAKeyframeAnimation(帧动画)和CABasicAnimation;
CABasicAnimation包含CASpringAnimation
---------------------
作者:liyubao160
来源:CSDN
原文:https://blog.csdn.net/u011146511/article/details/79453287
版权声明:本文为博主原创文章,转载请附上博文链接!
*/
import UIKit
enum TransitionAnimType : Int {
case fade = 0, //淡入淡出
push, //推挤
reveal, //揭开
moveIn, //覆盖
cube, //立方体
suckEffect, //吮吸
oglFlip, //翻转
rippleEffect, //波纹
pageCurl, //翻页
pageUnCurl, //反翻页
cameraIrisHollowOpen, //开镜头
cameraIrisHollowClose, //关镜头
curlDown, //下翻页
curlUp, //上翻页
flipFromLeft, //左翻转
flipFromRight, //右翻转
ramdom //随机
}
enum TransitionSubType : Int {
case top = 0, //上
left, //左
bottom, //下
right, //右
ramdom //随机
}
enum TransitionCurve : Int {
case Default = 0, //默认
EaseIn, //缓进
EaseOut, //缓出
EaseInEaseOut, //缓进缓出
Linear, //线性
Ramdom //随机
}
class LYBCATransitonVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//调用
layerTransition(animTye: .ramdom, subType: .ramdom, curve: .Ramdom, duration: 2.0, layer: (self.view.layer))
}
func layerTransition(animTye: TransitionAnimType, subType: TransitionSubType, curve: TransitionCurve, duration: CGFloat, layer: CALayer) {
let key = "transition"//
if layer.animation(forKey: key) != nil {
layer.removeAnimation(forKey: key)
}
let transition = CATransition()
/// 动画时长
transition.duration = CFTimeInterval(duration)
/// 动画类型
transition.type = CATransitionType(rawValue: animationType(animType: animTye))
/// 动画方向
transition.subtype = CATransitionSubtype(rawValue: animationSubType(subType: subType))
/// 缓动函数
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName(rawValue: animationCurve(curve: curve)))
/// 完成动画删除
transition.isRemovedOnCompletion = true
layer.add(transition, forKey: key)//key可以传nil
}
/// 返回动画类型
private func animationType(animType: TransitionAnimType) -> String {
/// 设置转场动画类型
let animTypeArray = ["fade", "push", "reveal", "moveIn", "cube", "suckEffect", "oglFlip", "rippleEffect", "pageCurl", "pageUnCurl", "cameraIrisHollowOpen", "cameraIrisHollowClose", "curlDown", "curlUp", "flipFromLeft", "flipFromRight", "ramdom"]
return objectFromDataSource(array: animTypeArray, index: animType.rawValue, isRamdom: (TransitionAnimType.ramdom == animType)) as! String
}
/// 返回动画方向
private func animationSubType(subType: TransitionSubType) -> String {
let animSubTypeArray = [CATransitionSubtype.fromTop, CATransitionSubtype.fromLeft, CATransitionSubtype.fromBottom, CATransitionSubtype.fromRight]
return objectFromDataSource(array: animSubTypeArray, index: subType.rawValue, isRamdom: (TransitionSubType.ramdom == subType)) as! String
}
/// 返回动画曲线
private func animationCurve(curve: TransitionCurve) -> String {
let animCurveArray = [CAMediaTimingFunctionName.default, CAMediaTimingFunctionName.easeIn, CAMediaTimingFunctionName.easeOut, CAMediaTimingFunctionName.easeInEaseOut, CAMediaTimingFunctionName.linear]
return objectFromDataSource(array: animCurveArray, index: curve.rawValue, isRamdom: (TransitionCurve.Ramdom == curve)) as! String
}
/// 统一从数据返回对象
private func objectFromDataSource(array: Array<Any>, index: Int, isRamdom: Bool) -> AnyObject {
let count = array.count
let i = isRamdom ? Int(arc4random_uniform(UInt32(count))) : index
return array[i] as AnyObject
}
}
******自定义专场动画*******
参考:https://blog.csdn.net/hmh007/article/details/53837859
/***
自定义转场动画测试vc
*/
import UIKit
class LYBAutoDefineCATransitionTextVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor=UIColor.blue
let buttonView=UIView.init(frame: CGRect.init(x: 0, y: 100, width: WIDTH, height: 50))
view.addSubview(buttonView)
let cancelBtn=UIButton.init(frame: CGRect.init(x: 20, y: 0, width: 100, height: 50))
cancelBtn.setTitle("返回", for: UIControl.State.normal)
cancelBtn.tag=10
cancelBtn.addTarget(self, action: #selector(sureOrcanceBtnClick), for: UIControl.Event.touchUpInside)
buttonView.addSubview(cancelBtn)
}
@objc func sureOrcanceBtnClick(sender:UIButton){
self.dismiss(animated: true, completion: nil)
}
}
********
/**
自定义转场动画,如果把LYBAutoDefineCATransitionTextVC换成UIViewcontroller就所有控制器都使适用
使用:
var tetxvc:LYBAutoDefineCATransitionTextVC?//要present出来的vc
tetxvc=LYBAutoDefineCATransitionTextVC()
self.present(tetxvc!,animated: true, completion: nil)
*/
import UIKit
class LYBAutoDefineCATRansitionVC: LYBAutoDefineCATransitionTextVC, UIViewControllerTransitioningDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
// 下面这两个函数定义在UIViewControllerTransitioningDelegate协议中
// 用于为present提供animator,
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
// 也可以使用CrossDissolveAnimator,动画效果各有不同
// return CrossDissolveAnimator()
return HalfWaySpringAnimator()
}
//用于为dismiss提供animator
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return LYBDismisTrasition()
}
}
************
/**
自定义转场动画的实现,presen出来时的动画
*/
import UIKit
class HalfWaySpringAnimator: NSObject, UIViewControllerAnimatedTransitioning {
/// 设置动画的持续时间
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 2
}
/// 设置动画的进行方式,附有详细注释,demo中其他地方的这个方法不再解释
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
let containerView = transitionContext.containerView
// 需要关注一下from/to和presented/presenting的关系
// For a Presentation:
// fromView = The presenting view.
// toView = The presented view.
// For a Dismissal:
// fromView = The presented view.
// toView = The presenting view.
var fromView = fromViewController?.view
var toView = toViewController?.view
// iOS8引入了viewForKey方法,尽可能使用这个方法而不是直接访问controller的view属性
// 比如在form sheet样式中,我们为presentedViewController的view添加阴影或其他decoration,animator会对整个decoration view
// 添加动画效果,而此时presentedViewController的view只是decoration view的一个子视图
if transitionContext.responds(to: #selector(transitionContext.view(forKey:))) {
fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)
toView = transitionContext.view(forKey: UITransitionContextViewKey.to)
}
// 我们让toview的origin.y在屏幕的一半处,这样它从屏幕的中间位置弹起而不是从屏幕底部弹起,弹起过程中逐渐变为不透明
toView?.frame = CGRect.init(x: fromView!.frame.origin.x, y: fromView!.frame.maxY / 2, width: fromView!.frame.width, height: fromView!.frame.height)
toView?.alpha = 0.0
// 在present和,dismiss时,必须将toview添加到视图层次中
containerView.addSubview(toView!)
let transitionDuration = self.transitionDuration(using: transitionContext)
// 使用spring动画,有弹簧效果,动画结束后一定要调用completeTransition方法
UIView.animate(withDuration: transitionDuration, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: .curveLinear, animations: { () -> Void in
toView!.alpha = 1.0 // 逐渐变为不透明
toView?.frame = transitionContext.finalFrame(for: toViewController!) // 移动到指定位置
}) { (finished: Bool) -> Void in
let wasCancelled = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!wasCancelled)
}
}
}
**********
/**
消失时的专场动画,dismis时的动画,也可以设置pop时的动画
*/
import UIKit
class LYBDismisTrasition: NSObject , UIViewControllerAnimatedTransitioning {
/// 设置动画的持续时间
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 2
}
/// 设置动画的进行方式,附有详细注释,demo中其他地方的这个方法不再解释
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
let containerView = transitionContext.containerView
// 需要关注一下from/to和presented/presenting的关系
// For a Presentation:
// fromView = The presenting view.
// toView = The presented view.
// For a Dismissal:
// fromView = The presented view.
// toView = The presenting view.
var fromView = fromViewController?.view
var toView = toViewController?.view
// iOS8引入了viewForKey方法,尽可能使用这个方法而不是直接访问controller的view属性
// 比如在form sheet样式中,我们为presentedViewController的view添加阴影或其他decoration,animator会对整个decoration view
// 添加动画效果,而此时presentedViewController的view只是decoration view的一个子视图
if transitionContext.responds(to: #selector(transitionContext.view(forKey:))) {
fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)
toView = transitionContext.view(forKey: UITransitionContextViewKey.to)
}
// 我们让toview的origin.y在屏幕的一半处,这样它从屏幕的中间位置弹起而不是从屏幕底部弹起,弹起过程中逐渐变为不透明
// toView?.frame = CGRect.init(x: fromView!.frame.origin.x, y: fromView!.frame.maxY / 2, width: fromView!.frame.width, height: fromView!.frame.height)
toView?.frame=CGRect.init(x: 0, y: 0, width: fromView!.frame.width, height: fromView!.frame.height)
toView?.alpha = 0.0
// 在present和,dismiss时,必须将toview添加到视图层次中
containerView.addSubview(toView!)
let transitionDuration = self.transitionDuration(using: transitionContext)
// 使用spring动画,有弹簧效果,动画结束后一定要调用completeTransition方法
UIView.animate(withDuration: transitionDuration, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: .curveLinear, animations: { () -> Void in
toView!.alpha = 1.0 // 逐渐变为不透明
toView?.frame = transitionContext.finalFrame(for: toViewController!) // 移动到指定位置
}) { (finished: Bool) -> Void in
let wasCancelled = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!wasCancelled)
}
}
}
let changeAnimation:CATransition=CATransition.init()
changeAnimation.delegate = self
changeAnimation.duration = 0.45
// CATransition 动画主要在过渡时使用,比如两个页面层级改变的时候添加一个转场效果。CATransition 分为两类,一类是公开的动画效果,一类是非公开的动画效果。
/*转场动画的属性
fade---交叉淡化过渡
push---新视图把旧视图推出
moveIn----新视图移动到旧视图上面
reveal----把旧视图移开,显示下面的新视图
cube---立体翻滚效果
oglFlip---上下左右翻转
1,公开动画效果:
kCATransitionFade:翻页
kCATransitionMoveIn:弹出
kCATransitionPush:推出
kCATransitionReveal:移除
2,非公开动画效果:
"cube":立方体
"suckEffect":收缩效果,如布块一样被抽走
"oglFlip":翻转
"rippleEffect":波纹
"pageCurl":卷页、翻页
"cameraIrisHollowOpen":镜头开
"cameraIrisHollowClose":镜头关
*/
changeAnimation.type = "oglFlip"//专场动画的属性
changeAnimation.subtype = kCATransitionFromRight//控制方向
changeAnimation.timingFunction = UIViewAnimationCurveEaseInOut
view.layer.addSublayer(changeAnimation)
==============imageview动画=============
let ar:[String]=["dw","xw","h01","h02","h03","h04","h05","h06","h07","h08","h09","h10","h11","h12","h13","ho01","ho02","ho03","ho04","ho05","ho06","ho07","ho08","ho09","ho10","ho11","ho12","ho13","f01","f02","f03","f04","f05","f06","f07","f08","f09","f10","f11","f12","f13","m01","m02","m03","m04","m05","m06","m07","m08","m09","m10","m11","m12","m13"]
var imgAr=[UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
for i in 0..<54{
let im:UIImage=UIImage.init(named: ar[i])!
imgAr.append(im)
}
let imagv:UIImageView=UIImageView.init(frame: CGRect.init(x: 50, y: 0, width: 50, height: 70))
view.addSubview(imagv)
imagv.animationImages=imgAr
//设置动画
imagv.animationDuration=20//动画时长
imagv.animationRepeatCount=1//重复播放次数
imagv.startAnimating()//开始动画
// imagv.stopAnimating()//停止动画
// let isA = imagv.isAnimating//是否正在动画
}