简体   繁体   中英

Convert UIBezierPath to UIImage

I'm creating a Apple Watch.So I accompanying a Iphone app in which I draw a Pie-graph using UIBezierPath . And i need to convert that graph to UIImage . Here is the code what i tried:

GraphView.m

 rectImage = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 260)];

 CGContextRef context = UIGraphicsGetCurrentContext();
 UIGraphicsPushContext(context);
 UIGraphicsBeginImageContext(rectImage.frame.size);

 CGFloat arcRadious = OUTER_RADIOUS;
 CGFloat tmpStartAngle = startAngle;
 CGFloat tmpEndAngle = endAngle;

 UIBezierPath *path = [[UIBezierPath alloc] init];
 path.lineWidth = 23;

 [path addArcWithCenter:centre radius:arcRadious startAngle:tmpStartAngle endAngle:tmpEndAngle clockwise:YES];

 [(UIColor*)_fillColours[index] setStroke];
 [path stroke];

 CGContextAddPath(context, path.CGPath);
 image = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsPopContext();
 UIGraphicsEndImageContext();

But in Apple Watch only some portion of the graph is showing. Can anyone tell me what wrong i did. Any help is greatly appreciated.

There are a few things wrong here - let's break it down bit by bit.


1: Creating The Context

CGContextRef context = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(context);
UIGraphicsBeginImageContext(rectImage.frame.size);

I'm not entirely sure what you're trying to do here.

What you're doing is getting the current context from the top of the stack (which might not even exist), then you're trying to push that context onto the stack again - which makes no sense as it's already on the stack (it's the current context!).

Then you're creating your image context, which will automatically push it onto the stack - making it the current context.

Therefore I'm assuming what you meant to do is this:

UIGraphicsBeginImageContext(rectImage.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();

This will create a new image context, make it the current context, and then get a reference to it.


2: Creating The Path

UIBezierPath *path = [[UIBezierPath alloc] init];
[path addArcWithCenter:centre radius:arcRadious startAngle:tmpStartAngle endAngle:tmpEndAngle clockwise:YES];

This could be problematic as you never move the path to a point before adding your arc - therefore it might not be drawn correctly.

You'll therefore want to move it to the arc's center point before adding it.

UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:centre];
[path addArcWithCenter:centre radius:arcRadious startAngle:tmpStartAngle endAngle:tmpEndAngle clockwise:YES];

3: Drawing The Path

[(UIColor*)_fillColours[index] setStroke];
[path stroke];

CGContextAddPath(context, path.CGPath); // <- Remove

Your third line here is unnecessary. This is because the stroke method on the UIBezierPath actually adds the bezier path to the current context and then strokes the path in that context.


4: Ending The Context

UIGraphicsPopContext(); // <- Remove
UIGraphicsEndImageContext();

Again, the image context will handle popping itself off the stack when you call UIGraphicsEndImageContext() , so trying to pop it yourself may cause issues.


Lastly, some pedantic details.

rectImage = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 260)];

Seeing as you're working with images in this code, the name rectImage is fairly misleading, as it's a UIView . I would rename to rectView .

CGFloat arcRadious = OUTER_RADIOUS;

I sincerely hope that OUTER_RADIOUS isn't a macro ( #define ). Constants should not be defined with a macro - they're not type safe and can make debugging a nightmare. Avoid them like the plague.

Instead, you should be using a static C constant. For example:

static CGFloat const kOuterRadius = 100.0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM