将UIBezierPath转换为UIImage

时间:2016-03-29 08:11:07

标签: ios objective-c uiimage watchkit uibezierpath

我正在创建一个Apple Watch。所以我在一个Iphone应用程序中使用 UIBezierPath 绘制了一个饼图。我需要将该图转换为 UIImage 。这是我尝试的代码:

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();

但在Apple Watch中,只显示了图表的某些部分。谁能告诉我我做错了什么。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

这里有一些问题 - 让我们一点一点地分解它。

1:创建上下文

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

我不完全确定你在这里要做什么。

你正在做的是从堆栈顶部获取当前上下文(可能甚至不存在),然后你试图再次将该上下文推送到堆栈 - 这没有任何意义,因为它是已经在堆栈上(这是当前的上下文!)。

然后你要创建你的图像上下文,它会自动将它推到堆栈上 - 使它成为当前的上下文。

因此,我假设你打算做的是:

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

这将创建一个新的图像上下文,使其成为当前上下文,然后获取对它的引用。

2:创建路径

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

这可能会有问题,因为在添加弧之前从未将路径移动到某个点 - 因此可能无法正确绘制。

因此,您需要在添加之前将其移动到圆弧的中心点。

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

3:绘制路径

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

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

这里的第三行是不必要的。这是因为stroke上的UIBezierPath方法实际上将贝塞尔路径添加到当前上下文,然后在该上下文中描绘路径。

4:结束上下文

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

同样,当您调用UIGraphicsEndImageContext()时,图像上下文将处理从堆栈中弹出的内容,因此尝试自行弹出可能会导致问题。

最后,一些迂腐的细节。

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

看到您在此代码中处理图片时,名称rectImage相当误导,因为它是UIView。我会重命名为rectView

CGFloat arcRadious = OUTER_RADIOUS;

我真诚地希望OUTER_RADIOUS不是宏(#define)。常量不应该用宏定义 - 它们不是类型安全的,可以使调试变成一场噩梦。像瘟疫一样避免它们。

相反,您应该使用static C常量。例如:

static CGFloat const kOuterRadius = 100.0