Core Graphics: Quartz2D
Animation related
Core Animation
Development steps
- To use it, you need to add the quartzCore. framework framework and import the main header file
- Initialize a CAAnimation object and set some animation-related properties
- Add CAAnimation to CALayer by calling CALayer’s addAnimation:forKey: method to start animation
- Animation in CALayer can be stopped by calling CALayer’s removeAnimationForKey: method
Pay attention to
- Core Animation works directly on CALayer, not UIView. Many properties in CALayer can be animated using CAAnimation, including opacity, position, Transform, Bounds, contents, etc. (search the API documentation: CALayer Animatable Properties)
- Core Animation executes animations in the background without blocking the main thread
CAAnimation inheritance structure
!
CAAnimation the parent class of all animation objects, which controls the duration and speed of the animation. CAAnimation is an abstract class. It should not be used directly, but should use its concrete subclasses :(red represents attributes from the CAMediaTiming protocol)
- Duration: indicates the duration of the animation
- RepeatCount: The number of times the animation is repeated
- RepeatDuration: Indicates the animation repetition time
- 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 fillMode to kcafillmodeforward
- FillMode: determines the behavior of the current object when it is not active. Before the animation starts, after the animation ends.
FillMode attribute value (For fillMode to work, it is best to set removedOnCompletion = NO)- KCAFillModeRemoved This is the default value, which means that before and after the animation, the animation has no effect on the layer, after the animation is finished, the layer will revert to its previous state
- Kcafillmodeforward After the animation ends, the layer will keep the final state of the animation
- KCAFillModeBackwards Before animation can start, all you need to do is add animation to a layer and the layer will go to the initial state of animation and wait for animation to start.
- KCAFillModeBoth is actually a combination of these two. After the animation is added, the layer is in the initial state of the animation until it starts, and after the animation is over, the layer remains in the last state of the animation
- BeginTime: can be used to set the animation delay. If you want to delay the animation for 2s, set it to CACurrentMediaTime()+2 CACurrentMediaTime() as the current time of the layer
- TimingFunction: a speed control function that controls the tempo of animation (CAMediaTimingFunction)
- KCAMediaTimingFunctionLinear (linear) : uniform, give you a relatively static feeling
- KCAMediaTimingFunctionEaseIn (gradual) : enter slowly, then accelerates to leave
- KCAMediaTimingFunctionEaseOut (gradually) : enter at full speed, and then slow to arrive
- KCAMediaTimingFunctionEaseInEaseOut (gradual fading out) : enter slow, intermediate speeds up, and then slow down to arrive at the destination. This is the default animation behavior.
- Delegate: Animation delegate
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
CAPropertyAnimation
CAKeyframeAnimation CABasicAnimation CABasicAnimation CAKeyframeAnimation CABasicAnimation CAKeyframeAnimation CABasicAnimation CAKeyframeAnimation
- KeyPath: Animation can be achieved by specifying a CALayer attribute named keyPath(NSString type) and modifying the value of this attribute in CALayer. For example, by specifying @ “position” as keyPath, CALayer’s position property is modified to animate the pan
CABasicAnimation Basic animation
CAPropertyAnimation subclass property parsing:
- FromValue: keyPath Specifies the initial value of the corresponding attribute
- ToValue: keyPath End value of the corresponding attribute
- As the animation progresses, the value of the keyPath attribute changes gradually from fromValue to toValue for a duration of duration
- if
fillMode=kCAFillModeForwards
andremovedOnComletion=NO
After the animation is executed, the layer will remain in the animation state. But in essence, the layer properties are the same as they were before the animation was executed and haven’t really changed. For example, CALayer’s position starts at (0,0), CABasicAnimation’s fromValue is (10,10), and toValue is (100,100). Essentially this layer’s position is still (0,0).
CAKeyframeAnimation Animation of keyframes
CApropertyAnimation is a subclass of CApropertyAnimation. It differs from CABasicAnimation in that: CABasicAnimation can only change from one value (fromValue) to another (toValue). CAKeyframeAnimation uses an NSArray to hold these values. Attribute parsing:
- Values: is the NSArray object described above. The elements inside are called keyframes. The animation object displays each keyframe in the values array in turn for a specified duration
- Path: You can set a path
CGPathRef\CGMutablePathRef
, let the layer follow the path. Path only works on CALayer’s anchorPoint and position. If you set path, values will be ignored - KeyTimes: you can specify a time point for a key frame. The value ranges from 0 to 1.0. Each time value in keyTimes corresponds to each frame in values. When keyTimes is not set, the time of each keyframe is evenly split
CABasicAnimation can be considered a CAKeyframeAnimation with at most two keyframes
CAAnimationGroup
A subclass of CAAnimation that can save a group of animation objects. After adding CAAnimationGroup objects to the layer, all animation objects in the group can be run concurrently. Attribute parsing:
- Animations: An NSArray used to hold a group of animated objects
- By default, a group of animation objects are run simultaneously, and the start time of the animation can also be changed by setting the beginTime property of the animation object
CATransition
A subclass of CAAnimation, used to animate transitions, that can animate layers off-screen and on-screen. IOS has a slightly less animated transition than Mac OS X. UINavigationController is a CATransition that implements the animation property resolution of the controller’s view onto the screen:
- Type: animation transition type
- Subtype: animation transition direction
- StartProgress: Animation starting point (percentage of total animation)
- EndProgress: End of animation (percentage of total animation)
Transition animation transition effect
UIView animation
UIKit integrates animation directly into the UIView class, and when some internal properties change, UIView provides animation support for those changes. The UIView class does all the work required to execute the animation automatically, but it still notifies the view when it wants to execute the animation, To do this, place the code that changes the properties between [UIView beginAnimations:nil Context :nil] and [UIView commitAnimations].
Common methods:
+ (void)setAnimationDelegate:(id)delegate: Set animation proxy objects, start or end when the animation will send a message to a proxy object + (void) setAnimationWillStartSelector: (SEL) the selector: When the animation is about to start, execute the selector of the delegate object, And the beginAnimations: context: the incoming parameters upon the selector + (void) setAnimationDidStopSelector: (SEL) the selector: When the animation ends, execute the selector of the delegate object, And pass the parameters passed in beginAnimations: Context: to selector + (void)setAnimationDuration (NSTimeInterval)duration: + (void)setAnimationDelay (NSTimeInterval) Delay + (void)setAnimationStartDate:(NSDate *)startDate: The start time of the animation, default is now + (void)setAnimationCurve:(UIViewAnimationCurve)curve: + (void)setAnimationRepeatCount:(float)repeatCount: Animation repeat number + (void) setAnimationRepeatAutoreverses: (BOOL) repeatAutoreverses: If set to YES, Representative animations repeat every time the effect will be contrary to the last time + (void) setAnimationTransition: (UIViewAnimationTransition) transition forView (UIView *) view Cache :(BOOL)cache: Sets the transition effect of view. Transition indicates the transition type. Cache: YES indicates that view cache is used, which has good performance
Block animation
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations; + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;Copy the code
Animations: Control the tempo of animations: Place the code that changes the properties of the view in the animations block completion: This block will be called automatically after the animation is completed
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;
Copy the code
// Add toView to superview [fromView. Superview addSubview:toView]; // Remove fromView from superview [fromView. Superview removeFromView];
For example, code for one view to fade out and another view to appear:
[UIView animateWithDuration:1.0 animations:^{firstView.alpha = 0.0; secondView.alpha = 1.0;}];Copy the code
How to achieve continuous animation? You can add animations to the Completion block. Here is an example code:
[UIView animateWithDuration:2.0 animations:^{oldiMageView. alpha =0.0; newImageView.alpha = 1.0; // Imageview.center = CGPointMake (500.0, 512.0);} completion:^(BOOL finished) {[UIView animateWithDuration:4.0 animations:^{newImageview.center = CGPointMake (500.0, 512.0);}]}];Copy the code
CALayer animation
-(void)pauseLayer:(CALayer*)layer {CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; Layer. speed = 0.0; Layer. timeOffset = pausedTime; layer.timeOffset = pausedTime; } #pragma mark resumeLayer -(void)resumeLayer:(CALayer*)layer {CFTimeInterval pausedTime = layer.timeoffset; // 1. Let CALayer's time continue to go layer.speed = 1.0; // 2. Cancel the layer.timeOffset = 0.0; // 3. Cancel layer.beginTime = 0.0; // 4. Calculate the pause time (CACurrentMediaTime()-pausedTime) CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; // 5. Set the start time relative to the parent coordinate system (timeSincePause backward) layer.beginTime = timeSincePause; }Copy the code
CADisplayLink
CADisplayLink is a clock mechanism that is triggered at a screen refresh rate, about 60 times per second. CADisplayLink is a timer that keeps the drawing code in sync with the view’s refresh rate, and NSTimer cannot be sure of the exact time when the timer is actually triggered. Usage:
- Define CADisplayLink and specify the trigger call method
- Add the display link to the main run loop queue
UIImageView frame animation
UIImageView allows a series of images to be displayed in sequence at a specific time: AnimationImages: the image to display (an NSArray containing UIImage) animationDuration: the time required to display all images in an animationImage completely at once – (void)startAnimating; : Start animation – (void)stopAnimating; : Stop animation – (BOOL)isAnimating; : Indicates whether animation is running
UIActivityIndicatorView
Progress is a rotating wheel, which can be used to inform the user have a operation is in progress, general use initWithActivityIndicatorStyle initialization method resolution: – (void) startAnimating. Start animation – (void)stopAnimating; Stop animation – (BOOL)isAnimating; Is running animation UIActivityIndicatorViewStyle has three values to choose from: UIActivityIndicatorViewStyleWhiteLarge / / large white indicator UIActivityIndicatorViewStyleWhite / / standard size white indicator UIActivityIndicatorViewStyleGray / / gray indicator for a white background
Quartz2D
Quartz2D API is pure C language. From Core Graphics. Is a 2d graphics engine that supports both iOS and Mac. Data types and functions are prefixed with CG, CGContextRef, CGPathRef, CGContextStrokePath(CTX). One of the most important values Quartz2D has in iOS development is the ability to customize views.
What Quartz 2D can do
- Draw graph: line, triangle, rectangle, circle, arc, etc
- Rendering text
- Draw \ Generate pictures (images)
- Read \ Generate PDF
- Screenshot \ Cropped picture
- Custom UI controls
- Doodle/sketchpad
- Gestures to unlock
Quartz2D provides the following types of Graphics Context:
- Bitmap Graphics Context
- PDF Graphics Context
- Window Graphics Context
- Layer Graphics Context
- Printer Graphics Context
The same set of drawing sequences, specifying different Graphics Context, can draw the same image to different targets:
Graphics Context
Is a CGContextRef type of data.
The role of the graphics context
- Save drawing information and drawing state
- Determine the output target to draw (where to draw?) The output target can be a PDF file, a Bitmap, or a monitor window.
How to use Quartz2D custom view? (Custom UI controls)
First, you have to have a graphics context, because it holds the drawing information and determines where the drawing goes. Second, that graphics context must be associated with the view in order to draw content onto the view.
Steps for customizing the View
- Create a new class that inherits from UIView
- implementation
- (void)drawRect:(CGRect)rect
Method, which then gets the graphics context associated with the current view - Draw the corresponding graphic content
- Use the graphics context to render everything drawn onto the view
Why do I need to implement the drawRect: method to draw onto the View?
Because you get the graph context associated with the view in the drawRect: method; The View has a layer property inside it, and the drawRect: method gets a Layer Graphics Context, so what’s being drawn is actually drawn onto the View’s layer; The View only displays things because of the layer inside it;
DrawRect: When is the method called?
Call the view’s setNeedsDisplay or setNeedsDisplayInRect: when the view is first displayed on the screen (which is added to UIWindow to display)
Quartz2D code
Quartz2D drawing code steps
- Get the graphics context
CGContextRef ctx = UIGraphicsGetCurrentContext();
- Splice path (the following code is to get a line segment)
CGContextMoveToPoint(ctx, 10, 10); CGContextAddLineToPoint(ctx, 100, 100);
- Draw the path
CGContextStrokePath(ctx); // CGContextFillPath(ctx);
Commonly used concatenation path functions
- Create a new starting point void CGContextMoveToPoint(CGContextRef C, CGFloat x, CGFloat Y)
- Add a new line segment to a point void CGContextAddLineToPoint(CGContextRef C, CGFloat x, CGFloat Y)
- Add a rectangle void CGContextAddRect(CGContextRef C, CGRect rect)
- Add an elliptic void CGContextAddEllipseInRect (CGContextRef context, CGRect the rect)
- Add a arc void CGContextAddArc(CGContextRef C, CGFloat X, CGFloat Y, CGFloat RADIUS, CGFloat startAngle, CGFloat endAngle, int clockwise)
Commonly used to draw path functions
- The Mode parameter determines the Mode to draw. Void CGContextDrawPath(CGContextRef C, CGPathDrawingMode Mode)
- Draw a hollow path void CGContextStrokePath(CGContextRef C)
- Draw a solid path void CGContextFillPath(CGContextRef C)
Note: CGContextDraw, CGContextStroke, and CGContextFill are all used to draw paths
Graphical context stack operations
- Void CGContextSaveGState(CGContextRef C) Void CGContextSaveGState(CGContextRef C)
- Void CGContextRestoreGState(CGContextRef C)
DrawLine draw line
- Get up and file UIGraphicsGetCurrentContext ();
- Set the starting point CGContextMoveToPoint(CTX, 10, 10);
- Add join point AddLineToPoint(CTX, 110, 10);
- Rendering CGContextStrokePath (CTX);
- CGContextSetLineWidth(CTX, 3);
- Set the line color CGContextSetRGBStrokeColor (CTX, 1, 0, 0, 1);
- Add another join point to complete the rectangle drawing
- CGContextSetLineCap(CTX, kCGLineCapButt);
- CGContextSetLineJoin(CTX, kCGLineJoinRound);
DrawRectangle draw rectangle
- Get up and file UIGraphicsGetCurrentContext ();
- Set the starting point and join the four points to form a rectangle CGContextMoveToPoint(CTX, 10, 10) AddLineToPoint(CTX, 110, 10); AddLineToPoint(ctx, 110, 110); AddLineToPoint(ctx, 110, 10); AddLineToPoint(ctx, 10, 10);
- The hollow CGContextStrokePath (CTX)
- Draw a solid CGContextFillPath (CTX);
- Use the CGContextStrokeRect (); / CGContextFillRect(); Draw a rectangular
Draw a triangle triangle
- Get up and file UIGraphicsGetCurrentContext ();
- Set the starting point and connect the three points
- Close the path CGContextClosePath(CTX);
- Rendering CGContextStrokePath (CTX)
Circle circle
CGContextAddEllipseInRect(context, CGRectMake(10, 10, 100, 100));
Draw arc arc
//x y dot // RADIUS //startAngle beginning Angle //endAngle Ending Angle // c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise) CGContextAddArc(context, 100, 100, 50, 0, M_PI_2, 1);
Painting fan sector
// Set the starting point of the sector path CGContextMoveToPoint(context, 100, 100); CGContextAddArc(context, 100, 100, 50, M_PI_4, 3 * M_PI_4, 0); CGContextClosePath(context);
UIBezierPath
You can create vector-based paths using the UIBezierPath class, which is in UIKit. This class is a wrapper around path from the Core Graphics framework. You can use this class to define simple shapes, such as ellipses or rectangles, or shapes with multiple lines and curved segments.
The BezierPath base UIBezierPath object is a wrapper around the CGPathRef data type. If the path is based on a vector shape, use lines and curves to create it. We use straight segments to create rectangles and polygons, and curved segments to create arcs, circles, and other complex curved shapes. Each paragraph contains one or more points, and the drawing command defines how to interpret those points. Where each line segment or curve segment ends is where the next one begins. Each set of connected lines or curve segments is called a subpath. A UIBezierPath object defines a complete path with one or more subPaths.
IOS UIBezierPath A common method for bezier curves
CALayer
The only reason UIView stays on screen is because of one layer inside it. When creating UIView objects, UIView inside will automatically create a new layer (namely CALayer object), through the UIView layer properties can access the layer @ property (nonatomic, readonly, retain) CALayer * layer; . When the UIView needs to be displayed on the screen, it calls the drawRect: method and draws everything on its own layer. When the drawing is done, the system copies the layers onto the screen and the UIView is displayed. UIView itself is more like a CALayer manager. You can have n calayers on a UIView, and each layer displays one thing, increasing the presentation power of UIView. Compared to CALayer, UIView has one more event handling function. So, if you don’t need to interact with the user, you can use UIView or CALayer. Of course, CALayer’s performance is higher because it lacks event handling and is more lightweight. First, CALayer is defined in the QuartzCore framework; CGImageRef and CGColorRef are defined in the CoreGraphics framework. UIColor and UIImage are defined in the UIKit framework; The QuartzCore and CoreGraphics frameworks are cross-platform and work on both iOS and Mac OS X. However, UIKit can only be used in iOS. To ensure portability, QuartzCore cannot use UIImage or UIColor, but only CGImageRef and CGColorRef.
Basic use of CALayer
- By manipulating the CALayer object, you can easily adjust the appearance properties of UIView, such as shadows, rounded corner size, border width, and color.
- You can also animate the layers for some cool effects.
The properties of CALayer
- @property CGRect bounds; Width and height;
- @property CGPoint position; Location (midpoint by default, as determined by anchorPoint). Sets the position of the CALayer in the parent layer. Take the upper-left corner of the parent layer as the origin (0, 0);
- @property CGPoint anchorPoint; Anchor points (x,y range 0-1) determine the meaning of position. Called “anchor point” and “anchor point”, it determines which point on CALayer will start from its upper left corner at the position indicated by the position attribute (0, 0). Its x and y values range from 0 to 1, and the default value is (0.5, 0.5).
- @property CGColorRef backgroundColor; Background color (CGColorRef type)
- @property CATransform3D transform; Deformation properties
- @property CGColorRef borderColor; Border color (CGColorRef type)
- @property CGFloat borderWidth; Border width
- @property GCFloat cornerRadius; radius
- @property(retain) id contents; Content (e.g. set to image CGImageRef)
What’s the difference between a UIView and a CLayer?
- UIView is the basis for iOS interface elements, from which all interface elements are inherited. It itself is completely implemented by CoreAnimation. The real drawing part of it is managed by a CALayer class. UIView itself is more like a CALayer manager, accessing its properties related to drawing and coordinates.
- UIView has an important property layer that returns its main CALayer instance.
- UIView’s CALayer is like a tree of subviews of UIView, and you can also add sublayers to its layer to do some particular representation. The CALayer layer can be nested.
- The layer tree of UIView is maintained inside the system in three copies. These are logical trees, which code can manipulate; The animation tree is an intermediate layer on which the system changes properties and performs various rendering operations. Display tree, whose contents are currently being displayed on the screen.
- Animation operation: Change the subLayer (non-main Layer) property of UIView and the animation will be generated automatically. The default duration of animation seems to be 0.5 seconds.
- Coordinate system: CALayer’s coordinate system has one more anchorPoint property than UIView, which is represented by CGPoint structure. The range is 0~1, which is a proportional value. This point is the origin of the coordinates of the various graph transformations and also changes the position of the layer. Its default value is {0.5,0.5}, which is in the center of the layer.
- Render: When updating layers, changes are not immediately displayed on the screen. When all the layers are ready, the setNeedsDisplay method can be called to redraw the display.
- Transform: to add a 3D or affineTransform to a layer, set the transform or affineTransform property of the layer, respectively.
- Morphing: Quartz Core’s rendering capabilities allow 2d images to be freely manipulated as if they were 3d. Images can be rotated, scaled and tilted at any Angle in a three-dimensional coordinate system. CATransform3D’s set of methods provides some magical transformation effects.
CALayer’s implicit animation
Implicit animation Each UIView has a CALayer associated with it by default. We can call this Layer Root Layer. All non-root Layer, manually created CALayer objects, have implicit animations;
- What is implicit animation?
Some animation is automatically generated by default when some properties of a non-root Layer are modified. These Properties are called Animatable Properties.
-
To list a few common Animatable Properties: Bounds: Used to set the width and height of the CALayer. Modifying this property produces a scaling animation. BackgroundColor: used to set the backgroundColor of CALayer. Changing this property produces a gradient animation of the background color. Position: Used to set the position of CALayer. Modifying this property produces a pan animation.
-
You can turn off the default implicit animation effects through animation transactions (CATransaction)
[CATransaction begin]; [CATransaction setDisableActions:YES]; self.myview.layer.position = CGPointMake(10, 10); [CATransaction commit]; Copy the code