将 UIBezierPath 转换为 UIImage
Convert UIBezierPath to UIImage
我正在创建一个 Apple Watch.So 我附带了一个 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:创建上下文
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
我正在创建一个 Apple Watch.So 我附带了一个 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:创建上下文
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