IOS Development --- drawing
Drawing operations
In iOS development, the system has provided us with powerful controls, but many of them cannot meet our needs. At this time, we need to customize some beautiful controls. The knowledge used is the drawing below.
1. Basic Drawing knowledge 1.1 graphic Context
1.1 Graphics Context: A CGContextRef type data
1.2 role of image Context
Save drawing information and drawing status
Determine the output target (where to draw ?)
(The output target can be a PDF file, Bitmap, or display window)
1.2-(void) drawRect :( CGRect) rect function: used to draw what call: when the control is displayed for the first time rect: the current control's bounds1.2 drawing steps
1. Obtain the image context:
CGContextRef ctx = UIGraphicsGetCurrentContext();
2. Splicing path
Create a start 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 rect)
Add an arc
void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
3. Add the path to the context
The Mode parameter determines the draw Mode.
Void CGContextDrawPath (CGContextRef c, CGPathDrawingMode mode)
Draw a hollow path
Void CGContextStrokePath (CGContextRef c)
Draw solid path
Void CGContextFillPath (CGContextRef c)
Tip: Generally, functions starting with CGContextDraw, CGContextStroke, and CGContextFill are used to draw paths.
4. rendering to View
1.3 Basic Drawing example
1. draw lines
Obtain the image context:
UIGraphicsGetCurrentContext()
Splicing path:
UIBezierPath
Add path to context
CGContextAddPath(ctx, path.CGPath)
Rendering to View
CGContextStrokePath(ctx)
-(Void) drawLine {// a path object, which can correspond to multiple heel lines // 1. obtain the context associated with the current view. The system automatically creates the context CGContextRef ctx = UIGraphicsGetCurrentContext (); // sets the context status, you should be able to create the corresponding color object before rendering, and call the set method [[UIColor redColor] set]; // set the context width CGContextSetLineWidth (ctx, 15 ); // set the connection style CGContextSetLineJoin (ctx, kCGLineJoinRound) of a line segment; // set the endpoint style CGContextSetLineCap (ctx, kCGLineCapRound) of a line segment; // 2. splicing path, UIBezierPath, encapsulates a set of well-used paths UIBezierPath * path = [UIBezierPath bezierPath]; // 2.1 sets the starting point [path moveToPoint: CGPointMake (10,125)]; // 2.2 add a line to a certain point [path addLineToPoint: CGPointMake (220,125)]; // if only one path is used, by default, the start point of the next line is at the end point of the last line. [path addLineToPoint: CGPointMake (200,150)]; // 3. add the path to the context CGContextAddPath (ctx, path. CGPath); // 4. layer CGContextStrokePath (ctx) rendered to the view );}
2. Draw a curve
Generally, the plot is drawn using the besell curve:UIBezierPath
-(Void) drawLIneQuadCurve {// 1. obtain the context CGContextRef ctx = UIGraphicsGetCurrentContext (); // 2. splicing path UIBezierPath * path = [UIBezierPath bezierPath]; [path moveToPoint: CGPointMake (10,125)]; [path addQuadCurveToPoint: CGPointMake (240,125) controlPoint: CGPointMake (125, 0)]; // 3. path to the context CGContextAddPath (ctx, path. CGPath); // 4. rendering context // rendering in a filled manner // CGContextFillPath (ctx); CGContextStrokePath (ctx );}
3. Draw a rectangle
// Draw a rectangle-(void) drawRect {CGContextRef ctx = forward (); UIBezierPath * path = [UIBezierPath paths: CGRectMake (50, 50,100,100) cornerRadius: 50]; CGContextAddPath (ctx, path. CGPath); // set the fill color [[UIColor redColor] setFill]; [UIColor greenColor] setStroke]; // fill: path that must be closed // that is, stroke and fill // If you only need to draw the edge later, it is best not to use fill CGContextDrawPath (ctx, kCGPathFillStroke); // CGContextFillPath (ctx ); CGContextStrokePath (ctx );}
4. Draw an arc
-(Void) drawRect :( CGRect) rect {// draw an arc // center: center // radius: radius // clockwise: current is yes: clockwise no: counter-clockwise CGPoint center = CGPointMake (125,125); UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter: CGPointMake (125,125) radius: 100 startAngle: 0 endAngle:-M_PI_2 clockwise: NO]; // Add a line to the center [path addLineToPoint: center]; // close the path: from the end of the path to the start point // [path closePath]; // fill, the path is disabled by default, from the end of the path to the start point [path fill];}
5. Draw text
-(Void) drawRect :( CGRect) rect {// ========================================= ====================== NSString * name = @ long GUI daisies; // description text attributes, color, font size NSMutableDictionary * attr = [NSMutableDictionary dictionary]; // font attr [NSFontAttributeName] = [UIFont systemFontOfSize: 15]; // color attr [NSForegroundColorAttributeName] = [UIColor redColor]; // border color attr [NSStrokeColorAttributeName] = [UIColor redColor]; // Border Width attr [NSStrokeWidthAttributeName] = @ 1; // shadow NSShadow * shadow = [[NSShadow alloc] init]; shadow. shadowOffset = CGSizeMake (3, 3); shadow. shadowColor = [UIColor yellowColor]; shadow. shadowBlurRadius = 3; attr [NSShadowAttributeName] = shadow; [name drawInRect: CGRectMake (90,100,100, 50) withAttributes: attr];}
6. Draw a pie chart
During initialization, the system calls the drawRect Method for plotting. However, it is invalid to manually call the drawRect method to reproduce the image. However, the system has prepared the re-painting method for us:
Redraw:setNeedsDisplay
-(Void) drawRect :( CGRect) rect {// Drawing code NSArray * datas = @ [@ 25, @ 25, @ 50]; CGPoint center = CGPointMake (125,125 ); CGFloat r = 100; CGFloat startA = 0; CGFloat angle = 0; CGFloat endA = 0; for (NSNumber * number in datas) {// traverse a data, draw a sector startA = endA; angle = number. intValue/100.0 * M_PI * 2; endA = startA + angle; // describe the arc UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter: center radius: r startAngle: startA endAngle: endA clockwise: YES]; [path addLineToPoint: center]; [[self randomColor] set]; [path fill] ;}// when you click View, redraw-(void) touchesBegan :( NSSet *) touches withEvent :( UIEvent *) event {[self setNeedsDisplay];} // generate a random color-(UIColor *) randomColor {CGFloat r = arc4random_uniform (256) /255.0; CGFloat g = arc4random_uniform (256)/255.0; CGFloat B = arc4random_uniform (256)/255.0; return [UIColor colorWithRed: r green: g blue: B alpha: 1];}
7. Context Stack
Copy the current context to the top of the stack (the stack is called "graphic context stack "):
void CGContextSaveGState(CGContextRef c)
Replace the context at the top of the stack with the current context:
void CGContextRestoreGState(CGContextRef c)
-(Void) drawRect :( CGRect) rect {// Drawing code // 1. obtain the context CGContextRef ctx = UIGraphicsGetCurrentContext (); // 2. splicing path UIBezierPath * path = [UIBezierPath bezierPath]; // horizontal [path moveToPoint: CGPointMake (10,150)]; [path addLineToPoint: CGPointMake (290,150)]; // 3. add the path to the context CGContextAddPath (ctx, path. CGPath ); // ================================================ ============/// Save the context status CGContextSaveGState (ctx ); // ================================================ ==============/// set the context status CGContextSetLineWidth (ctx, 10); [[UIColor redColor] set]; // 4. render the context, view the context status, and render CGContextStrokePath (ctx) based on the status; // vertical path = [UIBezierPath bezierPath]; [path moveToPoint: CGPointMake (150, 10)]; [path addLineToPoint: CGPointMake (150,290)]; // 3. add the path to the context CGContextAddPath (ctx, path. CGPath ); // ================================================ ==========/// retrieve the saved status from the context state stack, replace the current status CGContextRestoreGState (ctx ); // ================================================ ========/// 4. render the context, view the context status, and render CGContextStrokePath (ctx) according to the status );}
8. Context translation, rotation, and scaling
With matrix operations, all paths drawn to the context can change together.
Zoom
void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)
Rotate
void CGContextRotateCTM(CGContextRef c, CGFloat angle)
Translation
void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)
-(Void) drawRect :( CGRect) rect {// obtain the context CGContextRef ctx = UIGraphicsGetCurrentContext (); // The splicing path UIBezierPath * path = [UIBezierPath failed: CGRectMake (-100, -50,200,100)]; // matrix operation: Deformation must be performed before the path is added // translation context CGContextTranslateCTM (ctx, 100,100); // rotate CGContextRotateCTM (ctx, M_PI_4 ); // scale CGContextScaleCTM (ctx, 0.5, 0.5); // Add the path to the context CGContextAddPath (ctx, path. CGPath); // render the context CGContextFillPath (ctx );}
9. Add watermarks to images
1. Enable a bitmap-based image Context
void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)
Size: context size opaque: not transparent Yes NO scale: whether to scale the context. 0 indicates not to scale
2. Obtain the image (UIImage) from the context ):
UIImage* UIGraphicsGetImageFromCurrentImageContext()
3. Terminate the bitmap-based image context:
void UIGraphicsEndImageContext()
-(Void) viewDidLoad {enable a bitmap-based image context void Merge (CGSize size, BOOL opaque, CGFloat scale) [super viewDidLoad]; UIImage * image = [UIImage imageNamed: @ hina]; // creates the bitmap context uigraphicsbeginimagecontextwitexceptions (image. size, NO, 0); [image drawAtPoint: CGPointZero]; // text NSString * str = @ long GUI daisies; [str drawAtPoint: CGPointMake (0, 0) withAttributes: nil]; // generate an image = UIGraphicsGetImageFromCurrentImageContext () based on the context; // disable the context UIGraphicsEndImageContext (); // used to transmit images in the network NSData * data = UIImagePNGRepresentation (image); [data writeToFile: @/Users/apple/Desktop/image.png atomically: YES];}
10. Crop Images
1. Crop the paths drawn up and down (none of the paths beyond this cropping area are displayed ):
void CGContextClip(CGContextRef c)
Train of Thought Analysis
First draw a large circle, in the Set crop area, draw the picture, beyond the crop area automatically crop out.
* Load the old image and obtain the context size based on the old image.
* Determine the ring width borderW
* Context size = size of the new image
* Determine the new context size: newImageW: oldImageW + 2 * borderW newImageH: oldImageH + 2 * borderW,
* Draw a circle:
1. Get the context 2. Add the path to the context 3. Set the color of the circle to the color of the ring 4. Rendering
* Set the crop area, which is the same size as the image, except that x and y are different. x = borderW and y = borderW.
* Draw an old image
* Getting new images
* Disable Context
* Classification, three parameters, image name, ring width, and ring color
+ (UIImage *) imageCircleWithImage :( UIImage *) image borderWidth :( CGFloat) borderWidth borderColor :( UIColor *) borderColor {// set the ring width CGFloat boardW = borderWidth; CGFloat imageW = image. size. width + 2 * boardW; CGFloat imageH = image. size. height + 2 * boardW; // select the shortest size and tangent when only the square can be fully split. CGFloat circleW = imageW> imageH? ImageH: imageW; CGRect rect = CGRectMake (0, 0, circleW, circleW); // 2. Enable image context uigraphicsbeginimagecontextwitexceptions (rect. size, NO, 0.0); // 3. Obtain the current context CGContextRef ctx = UIGraphicsGetCurrentContext (); // 4. UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect: rect]; CGContextAddPath (ctx, path. CGPath); [borderColor set]; CGContextFillPath (ctx); // set the Avatar size rect = CGRectMake (boardW, boardW, image. size. width, image. size. height); // 5. create the cropping path UIBezierPath * clipPath = [UIBezierPath bezierPathWithOvalInRect: rect]; // 6. crop path // based on this path. [clipPath addClip] is not displayed for any part beyond the path; // 7. picture [image drawInRect: rect]; // It cannot be returned directly here. If the context is not disabled, the memory will be consumed. // 8. get new image = UIGraphicsGetImageFromCurrentImageContext (); // 9. disable the context UIGraphicsEndImageContext (); return image ;}
11. Capture the screen
The reason why a View can display things is its internal layer. The View has a layer attribute. drawRect: The method obtains a Layer Graphics Context. Therefore, what you draw is actually drawn to the view layer.
- (void)renderInContext:(CGContextRef)ctx;
// Capture the screen + (UIImage *) imageWithCaptureView :( UIView *) captureView; {// 1. enable the context uigraphicsbeginimagecontextwitexceptions (captureView. bounds. size, NO, 0.0); // 2. obtain the current context CGContextRef ctx = UIGraphicsGetCurrentContext (); // 3. render the Controller layer to the context [captureView. layer renderInContext: ctx]; // 4. retrieve new image UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext (); UIGraphicsEndImageContext (); return newImage ;}