IOS animation

Git code address

There are three kinds of animations commonly used in iOS development:

  • UIViewAnimation animation
  • CoreAnimation CoreAnimation
  • Other animation

[TOC]

UIView’s two animation apis contain method forms and block forms, which contain three animation implementations

  • UIView(UIViewAnimation)
  • UIView (UIViewKeyframeAnimation)
  • UIViewControllerAnimatedTransitioning

### function

Uiview. beginAnimations("Identifier"Context: nil)/agent/set animation UIView. SetAnimationDelegate (self) / / by#selector adds the start animation method
UIView.setAnimationWillStart(#selector(animationAction))/ / by#selector adds the end animation method
UIView.setAnimationDidStop(#selector(animationAction))/ / set the animation time interval UIView. SetAnimationDuration (1.0) / / set the animation delay UIView. SetAnimationDelay (0) / / set the starting time of the animation, Uiview.setanimationstart (Date()) uiView.setAnimationCurve (.easeInOut) uiView.setAnimationCurve (.easeInout) The default is 0 UIView. SetAnimationRepeatCount (0) / / 0 wireless loop / / automatically return to original state UIView. SetAnimationRepeatAutoreverses (false) // default = NO. used ifRepeat Count is non-zero // Sets the start of the animation to start from the present state, which is the defaultfalse
UIView.setAnimationBeginsFromCurrentState(false) / / used to display UIView animation on or off. The setAnimationsEnabled (true) / / set the animation transition effects UIView. SetAnimationTransition (. CurlUp,for: redView, cache: falseRedview. transform = CGAffineTransform(rotationAngle: 50) redView.transform = CGAffineTransform(scaleX: 0.3, y: 0.3) redview. transform = CGAffineTransform(scaleX: 0.3, y: 0.3) redview. transform = CGAffineTransform(translationX: 0, y: 200) // Animation stateprint(UIView. AreAnimationsEnabled) / / logo animation code ends, the program will create a new thread, and ready to run the animation UIView.com mitAnimations ()Copy the code
UIView.beginAnimations("Identifier", context: nil)
UIView.setAnimationDuration(1)
objectView.center.x = objectView.center.x + 100
UIView.commitAnimations()
Copy the code

The ###block form encapsulates the animation implementation in a block area, and the parameters are built on class methods.

UIView.animate(withDuration: TimeInterval, animations: ()->Void) UIView.animate(withDuration: TimeInterval, animations: Uiview.animate (withDuration: TimeInterval, delay: TimeInterval, options: UIViewAnimationOptions, animations: ()->Void, completion: (()->Void)?) Uiview. animate(withDuration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: 0, initialSpringVelocity: 0, options: UIViewAnimationOptions, animations: ()->Void, completion: (()->Void)?)Copy the code
Uiview.animate (withDuration: 1.0) {self.objectView.center.x = self.objectView.center.x-100}Copy the code

More parameter animation functions

//.curveeasein,.autoreverse,.repeat uiView.animate (withDuration: 1.0, delay: 0, options: [.curveEaseIn, .autoreverse, .repeat], animations: { self.objectView.center.x = self.objectView.center.x - 100 }, completion: nil) //delay UIView.animate(withDuration: 1.0, delay: 0.5, options:. CurveEaseIn, animations: { self.objectView2.center.x = self.objectView2.center.x - 100 }, completion: nil)Copy the code

The meanings of each parameter

Duration: the Duration of animations delay: how long after the last animation has been executed before the next animation can be executed options: the animations we want to achieve completion: the things we still want to do after the animations have been executedCopy the code

options

1. Set properties

UIViewAnimationOptionLayoutSubviews / / in the process of animation that child views follow sports UIViewAnimationOptionAllowUserInteraction / / allow user interaction in the process of animation UIViewAnimationOptionBeginFromCurrentState / / all views from the current state run UIViewAnimationOptionRepeat / / repeat the animation UIViewAnimationOptionAutoreverse / / animation after running to the end point is still in animation way back to the initial point UIViewAnimationOptionOverrideInheritedDuration / / ignore nested animation time Settings UIViewAnimationOptionOverrideInheritedCurve / / ignore nested animation speed setting UIViewAnimationOptionAllowAnimatedContent / / Redraw the view in the process of animation (note that only applies to ferry animation UIViewAnimationOptionShowHideTransitionViews / / view switch directly to hide old view, shows a new view, Not removed the old view from the parent view (only applicable to ferry animation) UIViewAnimationOptionOverrideInheritedOptions / / no father animation or animation set typeCopy the code

2. Animation speed control

UIViewAnimationOptionCurveEaseInOut / / animation first slow, Then gradually accelerated UIViewAnimationOptionCurveEaseIn gradually slowing UIViewAnimationOptionCurveEaseOut / / / / animation animation gradually accelerated Uniform execution UIViewAnimationOptionCurveLinear / / animation, the default valueCopy the code

3. Transition type (only applicable to transition animation Settings, you can choose one of them to set, basic animation, keyframe animation do not need to set)

UIViewAnimationOptionTransitionNone effect UIViewAnimationOptionTransitionFlipFromLeft / / / / no transitions animation from the left side of the rollover effect UIViewAnimationOptionTransitionFlipFromRight / / from the right side of the rollover effect UIViewAnimationOptionTransitionCurlUp / / flip back animation transition effects UIViewAnimationOptionTransitionCurlDown / / flip forward animation UIViewAnimationOptionTransitionCrossDissolve / / transition effects The old view solution showed the effects of the next new view UIViewAnimationOptionTransitionFlipFromTop / / flip effect UIViewAnimationOptionTransitionFlipFromBottom down from above // Flip effect from bottomCopy the code

Supported animation properties

Frame // Size changes: Change the frame and boundary of the view. Bounds // Stretch changes: Changes the stretch area of the view's content. Transform // Affine transform alpha // Change transparency: Change the alpha value of the view. BackgroundColor // change the backgroundColor contentStretch // stretch the contentCopy the code
  • Opacity — Sets Opacity
Uiview.animate (withDuration: 1.0) {self.objectView.alpha = 0.2}Copy the code
  • Scale — Zoom in and out
UIView. The animate (withDuration: 1.0) {self. ObjectView. Transform = CGAffineTransform (scaleX: 2, y: 2)} uiView.animate (withDuration: 1.0, delay: 1.0, options:.curvelinear, animations: {the self. The objectView. Transform = CGAffineTransform (scaleX: 0.5, y: 0.5)}, completion: nil)Copy the code
  • Translation, Translation
UIView. The animate (withDuration: 1.0) {self. ObjectView. Transform = CGAffineTransform (translationX: 200, y: 200)}Copy the code
  • Color – Color
Uiview.animate (withDuration: 1.0, delay: 0, options: [. Autoreverse,.repeat], animations: { self.objectView.backgroundColor = UIColor.brown }, completion: nil)Copy the code
  • Rotation – Rotation
Uiview.animate (withDuration: 1.0, delay: 0, options: [. CurveLinear,.repeat], animations: { self.objectView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi)) }, completion: nil)Copy the code

### Spring animation function

Uiview. animate(withDuration: 1.0, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 20, options: .curveEaseIn, animations: { self.objectView.center.y = self.objectView.center.y + 100 }, completion:nil)Copy the code

Keyframe animation

For the current view can contain one or more object keyframe animation animation block, and then based on the specified time ZhenZhen specified animation, need and addKeyframeWithRelativeStartTime: relativeDuration: animations: In combination with animations, note that if you do not add a keyframe animation object to the block, the animation will still execute, just as if you had called animateWithDuration(Duration: Delay: options: Animations: Completion:! To put it simply, calling this API creates an animation container to which you can then add multiple animations!

UIViewKeyframeAnimationOptions:

CalculationModeLinear: Linear transitions between frame animations 2.CalculationModeDiscrete: Not transitions between frame animations, execution of individual animations 3.CalculationModePaced: The effect of different frame animation try to merge into a more smooth animation 4. CalculationModeCubic: different frame animation algorithm adopts Catmull exemplifies Rom transition between 5. CalculationModeCubicPaced: 3 and 4, tried to know what effectCopy the code

AnimateKeyframesWithDuration: delay: options: animations: completion: combine, is used to specify the frame animation start time, duration and perform operations, one call can add a frame animation!

FrameStartTime: the start time of the frame animation. The value range is (0,1). The start time is relative to the entire animation time. 2 frameDuration: duration of frame animation. Value range: (0,1) duration of frame animation.Copy the code
UIView.animateKeyframes(withDuration: 10, delay: 0, options: .calculationModeCubicPaced, animations: {
     UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1/5, animations: {
         self.objectView.backgroundColor = UIColor.red
     })
     UIView.addKeyframe(withRelativeStartTime: 1/5, relativeDuration: 1/5, animations: {
         self.objectView.backgroundColor = UIColor.green
     })
     UIView.addKeyframe(withRelativeStartTime: 2/5, relativeDuration: 1/5, animations: {
         self.objectView.backgroundColor = UIColor.yellow
     })
     UIView.addKeyframe(withRelativeStartTime: 3/5, relativeDuration: 1/5, animations: {
         self.objectView.backgroundColor = UIColor.purple
     })
     UIView.addKeyframe(withRelativeStartTime: 4/5, relativeDuration: 1/5, animations: {
         self.objectView.backgroundColor = UIColor.gray
     })
 }, completion: nil)
Copy the code

Transitions transition

Overanimation emphasizes that the view changes the content. There are two ways to do this

UIView.transition(with:, duration:, options:, animations:, completion:)
UIView.transition(from: , to:, duration:, options:, completion:)
Copy the code

The type of transition animation is an options (UIViewAnimationOptions)

.transitionFlipFromLeft,.transitionFlipFromRight
.transitionFlipFromTop,.transitionFlipFromBottom
.transitionCurlUp,.transitionCurlDown
.transitionCrossDissolve
Copy the code
if self.objectView.backgroundColor == UIColor.gray {
    self.objectView.backgroundColor = UIColor.blue
}else {
    self.objectView.backgroundColor = UIColor.gray
}
}, completion: nil)
Copy the code

ImageView animation

Performing animation on UIImageView is very simple, just provide the animationImages property. A UIImage array. The array code is frame by frame. When we call startAnimating, the images of the array will be played in turn. AnimationDuration determines the playback speed. AnimationRepeatCount specifies the number of repetitions (default is 0 for infinite repetitions), or the stopAnimating method is called to stop the animation.

UIImage has some class methods for constructing an image that can be animated for UIImageView:

The image array and duration are specified directly.

UIImage.animatedImage(with:, duration:)
Copy the code

Provide a single image name, which is automatically followed by a “0” (or “1” if it fails). Make this image the first image. The last digit adds up. (Know no picture or reach “1024”)

UIImage.animatedImageNamed(, duration: )
Copy the code

Similar as above, but each image is stretched or tiled. The image itself also has a resizableImage(withCapInsets:, resizingMode:) method to scale (specify stretching or tiling of an area)

UIImage.animatedResizableImageNamed(, capInsets: , duration: )
Copy the code
let image = UIImage.animatedImageNamed("voice", duration: 2)
self.imageView.image = image
Copy the code

Voice1-3 has been named and placed in assets.xcassets

CoreAnimation works with Mac OS X and iOS platforms. Core Animation executes animations in the background. Does not block the main thread. Note that Core Animation works directly on CALayer. Is not a UIView

  • CABasicAnimation Basic animation
  • CAKeyframeAnimation Animation of keyframes
  • CATransition Transition animation
  • CAAnimationGroup group animation
  • CASpringAnimation (new after iOS9.0, CASpringAnimation, which implements spring animation, is a subclass of CABasicAnimation)

Animation operation process:

  • Create a CAAnimation object
  • Set some animation-related properties
  • AddAnimation to CALayer (addAnimation:forKey)
  • Remove animation from CALayer (removeAnimationForKey: method)

###CAAnimation (some attributes come from CAMediaTiming)

  1. Duration: duration of the animation. Default: 0.25 seconds

  2. Speed: Speed = 1.0 / duration = 1.0 animation effect is exactly the same as speed = 2.0 / duration = 2.0 animation effect. This also depends on speed.

  3. TimeOffset Sets the start and end time of the animation line

// Assume a 3s animation with states t0, T1, T2,t3. When there is no timeOffset, the normal state sequence would be: // T0 ->t1-> T2 ->t3 // When timeOffset is set to 1, the state sequence changes to // T1 -> T2 ->t3-> t1 // when timeOffset is set to 2, the state sequence changes to // T2 ->t3->t0-> T1Copy the code
  1. Autoreverses: Whether to automatically return to the animation start state

  2. RepeatCount: The number of times the animation is repeated

  3. RepeatDuration: Indicates the animation repetition time

  4. RemovedOnCompletion: Default is YES, which means that the animation will be removed from the layer after completion and the image will be restored to its original state. Set it to NO if you want the layer to look like it did after the animation was executed, but also set the fillMode property to kcafillmodeforward

  5. FillMode: determines the behavior of the current object when it is not active. Before the animation starts, after the animation ends

  6. BeginTime: can be used to set the animation delay. If you want to delay the animation for 2s, set it to CACurrentMediaTime()+2, CACurrentMediaTime() is the current time of the layer. The beginTime of CALayer is usually used for animation pause, while the beginTime of CAAnimation is usually used for animation delay, but only takes effect when groupAnimation is used. Adding the animation directly to the layer will cause the animation not to execute.

  7. TimingFunction: a speed control function that controls the tempo of the animation

Enumeration parameter:

KCAMediaTimingFunctionLinear time curve function, uniform kCAMediaTimingFunctionEaseIn time curve function, from slow to particularly fast kCAMediaTimingFunctionEaseOut time curve function, From fast to slow kCAMediaTimingFunctionEaseInEaseOut time curve function, from slow to fast kCAMediaTimingFunctionDefault system defaultCopy the code
  1. Delegate: Animation delegate, usually set to an implicit delegate, which is a class of NSObject that complies with the CAAnimationDelegate protocol
-(void)animationDidStart:(CAAnimation *)anim; -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag; Called after the core animation completes executionCopy the code

CAPropertyAnimation

Properties:

KeyPath: Specify a CALayer attribute name as the keyPath parameter (NSString type) and modify the value of this attribute in CALayer to achieve the corresponding animation effect. For example, by specifying @ “position” as keyPath, CALayer’s position property is modified to animate the pan.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
Copy the code

A summary of some commonly used animationWithKeyPath values

value instructions Use the form
transform.scale Proportion transformation @ (0.8)
transform.scale.x In proportion to the width @ (0.8)
transform.scale.y The proportion of high @ (0.8)
transform.rotation.x It’s rotating around the X-axis @(M_PI)
transform.rotation.y It’s rotating around the Y-axis @(M_PI)
transform.rotation.z It’s rotating around the z axis @(M_PI)
cornerRadius Rounded corner Settings @ (50)
backgroundColor Background color changes (id)[UIColor purpleColor].CGColor
bounds The magnitude, the center stays the same [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
position Position (change of center point) [NSValue valueWithCGPoint:CGPointMake(300, 300)];
contents Content, like a UIImageView image imageAnima.toValue = (id)[UIImage
opacity transparency @ (0.7)
contentsRect.size.width Transverse tensile scaling @(0.4) should be between 0 and 1

####CABasicAnimation CABasicAnimation can realize many animations, such as moving, rotating, zooming and scaling…. Everything KeyPath involves can be done

1. FromValue: keyPath Initial value of the corresponding attribute **2. Note: As the animation progresses, the value of the keyPath property changes from fromValue to toValue for a duration of duration. If fillMode = kcafillmodeforward and removedOnComletion = NO; After the animation is complete, the layer will remain as it was before the animation was executed, but in essence, the layer property value is the same as before the animation was executed, and it hasn’t really changed. Such as: The initial postion value of CALayer is (0,0), fromValue of CABasicAnimation is (10,10), and toValue of CABasicAnimation is (100,100), although the layer remains at (100,100) after the animation is completed. At this position, essentially the position on this layer is still (0,0); 3. ByValue: cumulative value (byValue plus fromValue => toValue)

Position

let baseAnimation = CABasicAnimation(keyPath: "position.x") baseAnimation.fromValue = objectView.center.x baseAnimation.toValue = objectView.center.x + 100 baseAnimation.duration = 1 / / retrograde animation baseAnimation autoreverses =trueBaseAnimation. RepeatCount = MAXFLOAT / / prevent animation return to original state after receiving baseAnimation. IsRemovedOnCompletion =false
baseAnimation.fillMode = CAMediaTimingFillMode.forwards

objectView.layer.add(baseAnimation, forKey: "demo")
Copy the code

Scale

let baseAnimation = CABasicAnimation(keyPath: "transform.scale") baseAnimation. FromValue = 0.5 baseAnimation. ToValue = 1 baseAnimation. Duration = 1 baseAnimation. RepeatCount = MAXFLOAT baseAnimation.fillMode = CAMediaTimingFillMode.forwards objectView.layer.add(baseAnimation,forKey: "demo")
Copy the code

####CASpringAnimation is an animation class that was introduced in iOS9. It inherits from CABaseAnimation and is used to animate springs

Parameter Description:

Mass: affects the inertia of the spring as the layer moves. The greater the mass, the greater the stretch and compression of the spring

1. The higher the stiffness factor, the greater the force generated by the deformation and the faster the movement

Damping coefficient, preventing spring expansion, the greater the damping coefficient, the faster the stop

InitialVelocity: the initialVelocity of the animated view. When the velocity is positive, the velocity direction is consistent with the direction of motion; when the velocity is negative, the velocity direction is opposite to the direction of motion

SettlingDuration: Returns the estimated time of the spring animation to stop. It is usually more accurate to estimate the spring animation time based on the current animation parameters

let springAnimation = CASpringAnimation(keyPath: "position.x")
springAnimation.damping = 5
springAnimation.stiffness = 100;
springAnimation.mass = 1;
springAnimation.initialVelocity = 0;
springAnimation.fromValue = objectView.layer.position.x;
springAnimation.toValue = objectView.layer.position.x + 50;
springAnimation.duration = springAnimation.settlingDuration;
objectView.layer.add(springAnimation, forKey: springAnimation.keyPath);
Copy the code

####CAKeyframeAnimation Animation of keyframes

  • The difference between CAKeyframeAnimation and CABasicAnimation is: CABasicAnimation can only change from one value (fromValue) to another (toValue). CAKeyframeAnimation uses an NSArray to hold these values.
  • CAKeyframeAnimation values: NSArray object. The elements inside are called keyframes. The animation object displays each keyframe in the values array in turn for the specified duration. Path: If you set path, Then values will be ignored. KeyTimes: You can specify a time point for each key frame. The value ranges from 0 to 1.0, and each time in keyTimes corresponds to each frame in Values. When keyTimes is not set, the time of each keyframe is evenly split. Note: CAKeyframeAnimation can be implemented as well as CABasicAnimation, and is more specific and accurate

Shake Sample

let shakeAnimation = CAKeyframeAnimation(keyPath: "transform.rotation") // Set the slosh AngleletShakeAnimation. Values = [Angle, -angle, Angle] shakeAnimation. Values = [Angle, -angle, Angle] shakeAnimation. KeyTimes = [0, 0.5, 1] // Set the number of iterations of the animation, . The default is 1 times shakeAnimation repeatCount = MAXFLOAT shakeAnimation. / / set the animation effect timingFunctions = [CAMediaTimingFunction (name: CAMediaTimingFunctionName. EaseIn)] / / set the animation transition way shakeAnimation. Adjacent calculationMode = CAAnimationCalculationMode. Cubic objectView.layer.add(shakeAnimation,forKey: shakeAnimation.keyPath);
Copy the code

Path animation

letMove (to: CGPoint(x: 40, y: 300)) path.addline (to: CGPoint(x: 80, y: 80)) path.addline (to: CGPoint(x: 80, y: 80) 150)) path.addLine(to: CGPoint(x: 120, y: 300)) path.addLine(to: CGPoint(x: 160, y: 150)) path.addLine(to: CGPoint(x: 200, y: 300))let bezierAnimation = CAKeyframeAnimation(keyPath: "position"// Since CAKeyframeAnimation's path is CGPath, // Set the animation time bezieranimation. duration = 4 // Automatically rotate the layer Angle to be tangent to path BezierAnimation. RotationMode = CAAnimationRotationMode. RotateAuto. / / set animation repetitions bezierAnimation repeatCount = MAXFLOAT / / set up automatic reverse bezierAnimation autoreverses =true
objectView.layer.add(bezierAnimation, forKey: nil)
Copy the code

Scale the animation

let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale"ScaleAnimation. Values = [0.0, 0.4, 0.8, 1.2, 1.6, 1.2, 0.8, 0.4, 0.0] scaleAnimation. Duration = 2 scaleAnimation. Autoreverses =true
scaleAnimation.repeatCount = MAXFLOAT
objectView.layer.add(scaleAnimation, forKey: nil)
Copy the code

Combining multiple animations and running a delegate and isRemovedOnCompletion concurrently in the animation’s properties array is currently ignored. The CAAnimationGroup’s delegate receives these messages

  • The animations array, used to add multiple CaAnimations
let animationPath = CAKeyframeAnimation.init(keyPath: "position") animationPath. Path = path. CgPath animationPath. RotationMode = CAAnimationRotationMode. RotateAuto / / rotatelet rotate:CABasicAnimation = CABasicAnimation()
rotate.keyPath = "transform.rotation"Rotate. ToValue = Double. PI // Shrink the image to 0let scale:CABasicAnimation = CABasicAnimation()
scale.keyPath = "transform.scale"Scale.tovalue = 0.0 // Combine animationletanimationGroup:CAAnimationGroup = CAAnimationGroup() animationGroup.animations = [animationPath,rotate,scale]; AnimationGroup. Duration = 2.0; animationGroup.fillMode = CAMediaTimingFillMode.forwards; animationGroup.isRemovedOnCompletion =false
objectView.layer.add(animationGroup, forKey:
    nil)
Copy the code

###CATransition transition animation

A subclass of CAAnimation provides animate transitions between layer states for objects that animate transitions between layers

CATransition has a Type and a subtype to identify the transformation effect

Newly added properties

  • StartProgress indicates the startProgress 0 to 1
  • Progress 0 to 1 at the end of endProgress
  • Type Conversion type
    • kCATransitionFade (default)
    • kCATransitionMoveIn
    • kCATransitionPush
    • kCATransitionReveal
  • The type introduced by API is not recognized on apple’s official website, so it is not recommended to use it
    • 1 animation.type = @”cube”; // Cube effect
    • 2 animation.type = @”suckEffect”; // Just like a piece of cloth
    • 3 animation.type = @”oglFlip”; // Flip up and down effect
    • 4 animation.type = @”rippleEffect”; // Drip effect
    • 5 animation.type = @”pageCurl”; // Turn the page left
    • 6 animation.type = @”pageUnCurl”; // Scroll down
  • Subtype A predefined transformation based on the direction of motion
    • kCATransitionFromLeft
    • kCATransitionFromRight
    • kCATransitionFromTop
    • kCATransitionFromBottom
  • The filter filter

** View Transaition**

letAnimation = CATransition() animation.duration = 1.0 animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) // `fade', `moveIn', `push' and `reveal'. Defaults to `fade'
animation.type = CATransitionType.reveal
// `fromLeft', `fromRight', `fromTop' and `fromBottom'
animation.subtype = CATransitionSubtype.fromLeft
//        animation.isRemovedOnCompletion = true
animation.startProgress = 0.5
objectView.layer.add(animation, forKey: nil)
Copy the code

** ViewController Transaition **

let vc = UIStoryboard(name: "Main", bundle: nil)
    .instantiateViewController(withIdentifier: "second")

let anima = CATransition.init()
//        anima.type = CATransitionType.reveal
anima.type = CATransitionType(rawValue: "pageUnCurl") anima. Subtype = CATransitionSubtype. FromLeft anima. Duration = 1.0 UIApplication. Shared) keyWindow?) layer. The add (anima,forKey: "pageUnCurl") // UIApplication.shared.keyWindow? .layer.removeAnimation(forKey: "pageUnCurl") self.navigationController? .pushViewController(vc, animated:false)
Copy the code

## Other animations

# # # animated transitions UIViewControllerAnimatedTransitioning controller

#### 1. Transition animation – Modal assigns value to vc’s transitioningDelegate attribute, and specifies the transition animation agent for the VC that is about to jump. There are two basic methods in the protocol, which require the agent to return the animation when present and the animation when dismiss.

class FadeTransitionDelegate: NSObject, UIViewControllerTransitioningDelegate {private lazy var fadeAnimator = fadeAnimator () / / provide dismiss the animation used when performing object func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        fadeAnimator.isPresenting = false
        returnFunc animationController(func animationController)forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        fadeAnimator.isPresenting = true
        return fadeAnimator
    }
}
Copy the code

Write a class to implement UIViewControllerAnimatedTransitioning animation agreement, as animation implementation class. And then the agent can return two animation implementation object, realize UIViewControllerTransitioningDelegate agency agreement.

Gets three views of the transition process: containerView, fromView, and toView. ContainerView is a temporary container provided during animation. FromView is the view of the transition start page. ToView is the view of the transition end page.

In the transition process, most of the time, we make various transformations to the toView, such as changing the toView’s alpha, size, rotation and so on. Before you can manipulate it, you need to put it in the Container to display it. [container addSubview:toView];

class FadeAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    
    letDuration = 1.0 var isPresenting =true/ / specify the duration of the animated transitions func transitionDuration (using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {returnFunc animateTransition(using transitionContext: UIViewControllerContextTransitioning) {/ / get the container viewletContainerView = transitionContext containerView / / target viewlet toView = transitionContext.view(forKey: UITransitionContextViewKey.to)! Containerview. addSubview(toView) // Add animations toView.alpha = 0.0 uiView. animate(withDuration: duration, animations: {toview.alpha = 1.0}, completion: {_in
            transitionContext.completeTransition(true)}}}Copy the code

The agent is finally assigned when presentViewController is presented

let transitionDelegate = FadeTransitionDelegate()
 @IBAction func UIViewControllerAnimatedTransitioning_Demo(_ sender: Any) {
     let vc = UIStoryboard(name: "Main", bundle: nil)
         .instantiateViewController(withIdentifier: "second")
     
     vc.transitioningDelegate = transitionDelegate
     present(vc, animated: true, completion: nil)
 }
Copy the code

# # # # 2, animated transitions – push process with transitions based usage – modal animation to customize the push animation, to realize the navigation controller UINavigationControllerDelegate agency agreement

class PushTansitionDelegate: NSObject, UINavigationControllerDelegate {private lazy var fadeAnimator = fadeAnimator var () / / do you need interaction interactive =falseNavigationController (_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {return fadeAnimator
    }
}
Copy the code

The fadeAnimator and Model have the same definition. Using Push animation

let vc = UIStoryboard(name: "Main", bundle: nil)
    .instantiateViewController(withIdentifier: "second") self.navigationController? .delegate = pushTransitionDelegate self.navigationController?.pushViewController(vc, animated:true)
Copy the code

#### i. Transitions – Interactive Transitions Interactive transitions are event-driven. It can be an action event or a gesture, usually a gesture. To implement an interactive transition, in addition to requiring the same animation as before, you also need to tell the interaction controller how much animation has been completed. The developer only needs to determine the percentage that has been completed and leave the rest to the system. For example, the amount of distance/speed of panning and scaling can be used as a parameter to calculate the percentage of completion.

Interactive controller implements UIViewControllerInteractiveTransitioning protocol:

- (void)startInteractiveTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
Copy the code

There can only be one animation block in this method, animations should be based on UIView and not layers, and interactive transitions do not support CATransition or CALayer animations.

Interactive interaction transition controller should be UIPercentDrivenInteractiveTransition subclasses. The animation class is responsible for calculating the percentage of completion, and the system automatically updates the intermediate state of the animation.

- (void)updateInteractiveTransition:(CGFloat)percentComplete;
- (void)cancelInteractiveTransition;
- (void)finishInteractiveTransition;
Copy the code

To add handlePan FadeAnimator, and inherit UIPercentDrivenInteractiveTransition supports interactive animation

class FadeAnimator: UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning {
    
    letDurationAnimation = 1.0 // present/dismiss, push/pop var isPresenting =trueVar interactive =false/ / specify the duration of the animated transitions func transitionDuration (using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {returnDurationAnimation} func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {/ / get the container viewletContainerView = transitionContext containerView / / target viewlet toView = transitionContext.view(forKey: UITransitionContextViewKey.to)! Toview. alpha = 0.0 uiView. animate(withDuration: DurationAnimation, animations: {toViet. alpha = 1.0}, Completion: {_in
            transitionContext.completeTransition(true)
        })
    }
    
    func handlePan(recognizer: UIPanGestureRecognizer) {
        let translation = recognizer.translation(in: recognizer.view! .superview!) Var progress: CGFloat = abs(translation.x / 200.0) progress = min(Max (progress, 0.01), 0.99) switch recognizer.state {case.changed: // Update the current transition progress update(progress)case .cancelled:
            cancel()
        case .ended:
            finish()
        default:
            break}}Copy the code

The corresponding Delegate has been changed to support an interactive transition animation:

class PushTansitionDelegate: NSObject, UINavigationControllerDelegate {private lazy var fadeAnimator = fadeAnimator var () / / do you need interaction interactive =falseNavigationController (_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {returnNavigationController (_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {if interactive == false {
            return nil
        }
        
        return fadeAnimator
    }
    

    func handlePan(recognizer: UIPanGestureRecognizer) {
        fadeAnimator.handlePan(recognizer: recognizer)
    }
}
Copy the code

The second page returns with an interactive transition animation

class SecondViewController: UIViewController {
     let pushTransitionDelegate = PushTansitionDelegate()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(recognizer:)))
        self.view.addGestureRecognizer(pan)
    }
    
    @objc func handlePan(recognizer: UIPanGestureRecognizer) {
        if recognizer.state == .began {
            
            pushTransitionDelegate.interactive = trueself.navigationController? .delegate = pushTransitionDelegate self.navigationController?.popViewController(animated:true)}else {
            pushTransitionDelegate.handlePan(recognizer: recognizer)
        }
    }
    
    @IBAction func close(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
}
Copy the code

UIDynamic is a set of dynamics framework that apple added after iOS7. With it, we can easily simulate real life motion, such as gravity, collision and so on. It involves dynamics in motion by adding behavior.

Dynamic behaviors provided in iOS7.0 include:

UIGravityBehavior: Gravity UICollisionBehavior: Collision UIAttachmentBehavior: Attachment UISnapBehavior: Attachment UIPushBehavior: UIDynamicItemBehavior: dynamic element behavior

UIDynamic is still relatively simple to use

1. First we create a small square objectView and place it in the top part of self.view. (Only objects that comply with the UIDynamicItem protocol can participate in the simulation, and UIView complies with this protocol, so all view controls can participate in the simulation)

2. Then define a UIDynamicAnimator (all objects that want to participate in the motion must be added to this container)

3. Add another gravity behavior to the emulator that applies to the boxView we defined earlier

4. You can see that the boxView placed in the upper part of self.view falls down due to gravity behavior. But it will fall out of the self.view scope.

5. In order not to fall out of the scope of self.view we need to add another behavior to the objectView: collision behavior. Touching the boundary of the simulator or any other container in the self.view will cause collisions.

6. In this way, the cubes will not fall out of the range of the emulator. Similarly, other behaviors will be used in the same way as above and must be added to the emulator to take effect.

var animator: UIDynamicAnimator!
@IBAction func UIDynamic_tap(_ sender: Any) {
    animator = UIDynamicAnimator(referenceView: self.view)
    let behavior = UIGravityBehavior(items: [objectView])
    animator.addBehavior(behavior)
    
    let behaviorCollision = UICollisionBehavior(items: [objectView])
    behaviorCollision.translatesReferenceBoundsIntoBoundary = true
    animator.addBehavior(behaviorCollision)
}
Copy the code

CAEmitterLayer particle animation

1, CAEmitterLayer. This is mainly to define the particle prototype emission layer shape and emission location, emission source size and emission mode.

2. CAEmitterCell Is the prototype of a single particle. There are usually multiple particles.

The parameters of these two classes may seem simple, but different combinations of these parameters, combined with corresponding images, can achieve many unexpected animation effects.

var rainLayer: CAEmitterLayer! @IBAction func CAEmitterLayer_tap(_ sender: Any) {rainLayer = CAEmitterLayer() The default launch upwards rainLayer. EmitterShape = CAEmitterLayerEmitterShape. Line / / from the outline of emitter particles rainLayer. EmitterMode = CAEmitterLayerEmitterMode. Outline / / priority rainLayer rendering of the old particles. The renderMode = CAEmitterLayerRenderMode. OldestFirst / / / / launch position For linear emitters, // (emitterPosition. x-emittersize. width/2, emitterPosition.y, X + emitterSize.width/2, emitterPosition.y, emitterZPosition) rainLayer.emitterPosition = CGPoint(x: view.bounds.midX, y: // Rainlayer. emitterSize = CGSize(width: view.bounds.width, height: 0) // Multiples of particle generation rate, not fired at first, set to zero rainlayer. birthRate = 0 // emitted particlesletCell = CAEmitterCell() // Set CGImage to cell.contents = UIImage(named:"star")? Cell. scale = 0.1 // Particle lifetime in seconds Cell. lifetime = 5 // Particle generation rate in seconds The actual display is multiplied by CAEmitterLayer's birthRate cell. BirthRate = 1000 // Particle velocity cell. Velocity = 500 // Particle emission Angle, A positive value means clockwise cell.emissionlongitude = cgfloat. PI // Layer to emit 1 particle Rainlayer. emitterCells = [cell] // Add particle emission layer View.layer.addsublayer (rainLayer) // Particle generation rate gradient animationlet birthRateAnimation = CABasicAnimation(keyPath: "birthRate")
    birthRateAnimation.duration = 3
    ifRainLayer. The birthRate = = 0 {/ rain/larger birthRateAnimation fromValue = 0 birthRateAnimation. ToValue = 1 rainLayer. BirthRate = 1}else{/ / rain smaller birthRateAnimation fromValue = 1 birthRateAnimation. ToValue = 0 rainLayer. BirthRate = 0} / / add animation rainLayer.add(birthRateAnimation,forKey: "birthRate")}Copy the code

Reference links www.jianshu.com/p/71f2fa270… www.jianshu.com/p/9aead7675… www.jianshu.com/p/802d47f0f…