【问题标题】:Convert UIBezierPath to UIImage将 UIBezierPath 转换为 UIImage
【发布时间】:2016-03-29 08:11:07
【问题描述】:

我正在创建 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 中,仅显示了图表的一部分。谁能告诉我我做错了什么。非常感谢任何帮助。

【问题讨论】:

标签: ios objective-c uiimage watchkit uibezierpath


【解决方案1】:

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


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

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


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

【讨论】:

  • 你能告诉我如何使用 Page-Based Navigation 在 Apple Watch 中显示这些图像
  • @JestinSajiChacko 请尽量不要在每个帖子中提出一个以上的问题 - 这会产生混淆,并且通常对未来的读者没有好处。我会继续问一个关于 Apple Watch 上的页面导航的新问题,并将这个问题回滚为关于在图像上下文中呈现 UIBezierPath
  • 好的。正如你所说,我问了另一个关于基于页面的导航的问题
猜你喜欢
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 2012-07-15
  • 2013-01-01
  • 2015-12-12
  • 2011-09-22
相关资源
最近更新 更多