是否可以从 uiview 获取所有 uibezerpath?
Is it possible to get all uibezerpath from uiview?
我一直在研究,但没有找到答案。
如果我使用 CGGontext 将其绘制到视图中,是否有可能在 UIView 中绘制一次后从 UIView 获取所有 UIBezierPath? (如果是,你能告诉我怎么做吗?)UIBezierPath 来自用户输入,所以如果用户绘制了很多 UIBezierPath,我需要所有这些路径并将其保存到 .svg 文件。
如果您正在使用 Core Graphics 绘制路径,您可能有一些模型支持 drawRect
可用于绘制所有路径的视图。如果您不这样做(即您只是更新位图),您应该简单地重构该代码以捕获和保存表示路径所需的信息。
这是一个更好的工作示例,在测试了我在评论中给出的一些答案之后,这个示例将 return 一组 shapelayer 或图层,具体取决于您要查找的内容:
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 196.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
NSLog(@"this is a layer: %@", rd);
}
}
NSLog(@"this is an Array of Shapes: %@", this);
CAShapeLayer 也可以只存储一条线,不管线有多复杂,如果它来自 UIBezierPath 并且你将它存储在你正在绘制的 UIView 的子层中,这个对象就可以存储它。事实上,为了进一步扩展,为了您的目的,请参阅以下内容,这将 return CGPath,根据您的问题,这就是您想要的:
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 96.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
CAShapeLayer * rf = (CAShapeLayer*)rd;
NSLog(@"this is a layer: %@", rf.path);
CGRect pathBounds = CGPathGetBoundingBox(rf.path);
NSLog(@"this is this boundingBox: origin.X: %f, origin.X: %f, size.Width: %f, size.Height: %f", pathBounds.origin.x, pathBounds.origin.y, pathBounds.size.width, pathBounds.size.height);
}
}
NSLog(@"this is an Array of Shapes: %@", this);
而且,如果您想更进一步,那么这可以用来存储 CGRect 坐标,而且,这将向您展示如何检索和使用这些坐标:
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 196.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
NSMutableArray *that = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
CAShapeLayer * rf = (CAShapeLayer*)rd;
NSLog(@"this is a layer: %@", rf.path);
CGRect pathBounds = CGPathGetBoundingBox(rf.path);
[that addObject:[NSValue valueWithCGRect:pathBounds]];
NSLog(@"this is this boundingBox: origin.X: %f, origin.X: %f, size.Width: %f, size.Height: %f", pathBounds.origin.x, pathBounds.origin.y, pathBounds.size.width, pathBounds.size.height);
}
}
现在,结束,这是对 https://github.com/erica/iOS-6-Cookbook 的改编,这是为了展示我绘制的 UIBezierPath 的完整解开:
#define VALUE(_INDEX_) [NSValue valueWithCGPoint:points[_INDEX_]]
-(void)showPaths
{
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 196.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
NSMutableArray *that = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
CAShapeLayer * rf = (CAShapeLayer*)rd;
NSLog(@"this is a layer: %@", rf.path);
CGRect pathBounds = CGPathGetBoundingBox(rf.path);
[that addObject:[NSValue valueWithCGRect:pathBounds]];
CGMutablePathRef p3 = CGPathCreateMutableCopy(rf.path);
NSArray *p3points = [self pointsFromCGPath:p3];
for (NSValue *point in p3points) {
NSLog(@"path element in p3: %@", NSStringFromCGPoint(point.CGPointValue));
}
NSLog(@"this is this boundingBox: origin.X: %f, origin.X: %f, size.Width: %f, size.Height: %f", pathBounds.origin.x, pathBounds.origin.y, pathBounds.size.width, pathBounds.size.height);
}
}
}
void getPointsFromBezier(void *info, const CGPathElement *element)
{
NSMutableArray *bezierPoints = (__bridge NSMutableArray *)info;
// Retrieve the path element type and its points
CGPathElementType type = element->type;
CGPoint *points = element->points;
switch (type) {
case kCGPathElementMoveToPoint:
NSLog(@"MoveToPoint (%3.2f, %3.2f", points->x, points->y);
break;
case kCGPathElementAddLineToPoint:
NSLog(@"AddLineToPoint (%3.2f, %3.2f)", points->x, points->y);
break;
case kCGPathElementAddQuadCurveToPoint:
NSLog(@"AddQuadCurveToPoint (%3.2f, %3.2f), (%3.2f, %3.2f)", points->x, points->y, points[1].x, points[1].y);
break;
case kCGPathElementAddCurveToPoint:
NSLog(@"AddCurveToPoint (%3.2f, %3.2f), (%3.2f, %3.2f), (%3.2f, %3.2f)", points->x, points->y, points[1].x, points[1].y, points[2].x, points[2].y);
break;
case kCGPathElementCloseSubpath:
NSLog(@"CloseSubpath (%3.2f, %3.2f)", points->x, points->y);
break;
default:
NSLog(@"unknown");
break;
}
// Add the points if they're available (per type)
if (type != kCGPathElementCloseSubpath)
{
[bezierPoints addObject:VALUE(0)];
if ((type != kCGPathElementAddLineToPoint) &&
(type != kCGPathElementMoveToPoint))
[bezierPoints addObject:VALUE(1)];
}
if (type == kCGPathElementAddCurveToPoint)
[bezierPoints addObject:VALUE(2)];
}
- (NSArray *)pointsFromCGPath:(CGPathRef)path
{
NSMutableArray *points = [NSMutableArray array];
CGPathApply(path, (__bridge void *)points, getPointsFromBezier);
return points;
}
输出将记录到控制台,所有存储在我们开始的 CAShapeLayer 中的路径,输出对于 post 来说太大太乱,但这是开始的样子:
[30146:2680987] MoveToPoint (103.82, 100.00
[30146:2680987] AddLineToPoint (296.75, 100.00)
[30146:2680987] AddLineToPoint (296.75, 144.00)
[30146:2680987] AddLineToPoint (103.82, 144.00)
[30146:2680987] AddCurveToPoint (102.72, 144.00), (102.17, 144.00),
(101.67, 143.84)
[30146:2680987] AddLineToPoint (101.58, 143.81)
[30146:2680987] AddCurveToPoint (100.93, 143.58), (100.42, 143.07),
(100.19, 142.42)
[30146:2680987] AddCurveToPoint (100.00, 141.83), (100.00, 141.28),
(100.00, 140.18)
[30146:2680987] AddLineToPoint (100.00, 103.82)
[30146:2680987] AddCurveToPoint (100.00, 102.72), (100.00, 102.17),
(100.16, 101.67)
[30146:2680987] AddLineToPoint (100.19, 101.58)
[30146:2680987] AddCurveToPoint (100.42, 100.93), (100.93, 100.42),
(101.58, 100.19)
[30146:2680987] AddCurveToPoint (102.17, 100.00), (102.72, 100.00),
(103.82, 100.00)
[30146:2680987] AddLineToPoint (103.82, 100.00)
[30146:2680987] path element in p3: {103.8216625, 100}
[30146:2680987] path element in p3: {296.75, 100}
[30146:2680987] path element in p3: {296.75, 144}
[30146:2680987] path element in p3: {103.8216625, 144}
[30146:2680987] path element in p3: {102.72123239404632, 144}
[30146:2680987] path element in p3: {102.17101736015751, 144}
我一直在研究,但没有找到答案。
如果我使用 CGGontext 将其绘制到视图中,是否有可能在 UIView 中绘制一次后从 UIView 获取所有 UIBezierPath? (如果是,你能告诉我怎么做吗?)UIBezierPath 来自用户输入,所以如果用户绘制了很多 UIBezierPath,我需要所有这些路径并将其保存到 .svg 文件。
如果您正在使用 Core Graphics 绘制路径,您可能有一些模型支持 drawRect
可用于绘制所有路径的视图。如果您不这样做(即您只是更新位图),您应该简单地重构该代码以捕获和保存表示路径所需的信息。
这是一个更好的工作示例,在测试了我在评论中给出的一些答案之后,这个示例将 return 一组 shapelayer 或图层,具体取决于您要查找的内容:
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 196.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
NSLog(@"this is a layer: %@", rd);
}
}
NSLog(@"this is an Array of Shapes: %@", this);
CAShapeLayer 也可以只存储一条线,不管线有多复杂,如果它来自 UIBezierPath 并且你将它存储在你正在绘制的 UIView 的子层中,这个对象就可以存储它。事实上,为了进一步扩展,为了您的目的,请参阅以下内容,这将 return CGPath,根据您的问题,这就是您想要的:
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 96.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
CAShapeLayer * rf = (CAShapeLayer*)rd;
NSLog(@"this is a layer: %@", rf.path);
CGRect pathBounds = CGPathGetBoundingBox(rf.path);
NSLog(@"this is this boundingBox: origin.X: %f, origin.X: %f, size.Width: %f, size.Height: %f", pathBounds.origin.x, pathBounds.origin.y, pathBounds.size.width, pathBounds.size.height);
}
}
NSLog(@"this is an Array of Shapes: %@", this);
而且,如果您想更进一步,那么这可以用来存储 CGRect 坐标,而且,这将向您展示如何检索和使用这些坐标:
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 196.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
NSMutableArray *that = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
CAShapeLayer * rf = (CAShapeLayer*)rd;
NSLog(@"this is a layer: %@", rf.path);
CGRect pathBounds = CGPathGetBoundingBox(rf.path);
[that addObject:[NSValue valueWithCGRect:pathBounds]];
NSLog(@"this is this boundingBox: origin.X: %f, origin.X: %f, size.Width: %f, size.Height: %f", pathBounds.origin.x, pathBounds.origin.y, pathBounds.size.width, pathBounds.size.height);
}
}
现在,结束,这是对 https://github.com/erica/iOS-6-Cookbook 的改编,这是为了展示我绘制的 UIBezierPath 的完整解开:
#define VALUE(_INDEX_) [NSValue valueWithCGPoint:points[_INDEX_]]
-(void)showPaths
{
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 196.75, 44.0) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:(CGSize){2.5, 2.5}].CGPath];
[[self.view layer] addSublayer:firstNameCorners];
NSMutableArray *this = [[NSMutableArray alloc] init];
NSMutableArray *that = [[NSMutableArray alloc] init];
for (CALayer * rd in self.view.layer.sublayers) {
if ([rd isKindOfClass:[CAShapeLayer class]]) {
[this addObject:rd];
CAShapeLayer * rf = (CAShapeLayer*)rd;
NSLog(@"this is a layer: %@", rf.path);
CGRect pathBounds = CGPathGetBoundingBox(rf.path);
[that addObject:[NSValue valueWithCGRect:pathBounds]];
CGMutablePathRef p3 = CGPathCreateMutableCopy(rf.path);
NSArray *p3points = [self pointsFromCGPath:p3];
for (NSValue *point in p3points) {
NSLog(@"path element in p3: %@", NSStringFromCGPoint(point.CGPointValue));
}
NSLog(@"this is this boundingBox: origin.X: %f, origin.X: %f, size.Width: %f, size.Height: %f", pathBounds.origin.x, pathBounds.origin.y, pathBounds.size.width, pathBounds.size.height);
}
}
}
void getPointsFromBezier(void *info, const CGPathElement *element)
{
NSMutableArray *bezierPoints = (__bridge NSMutableArray *)info;
// Retrieve the path element type and its points
CGPathElementType type = element->type;
CGPoint *points = element->points;
switch (type) {
case kCGPathElementMoveToPoint:
NSLog(@"MoveToPoint (%3.2f, %3.2f", points->x, points->y);
break;
case kCGPathElementAddLineToPoint:
NSLog(@"AddLineToPoint (%3.2f, %3.2f)", points->x, points->y);
break;
case kCGPathElementAddQuadCurveToPoint:
NSLog(@"AddQuadCurveToPoint (%3.2f, %3.2f), (%3.2f, %3.2f)", points->x, points->y, points[1].x, points[1].y);
break;
case kCGPathElementAddCurveToPoint:
NSLog(@"AddCurveToPoint (%3.2f, %3.2f), (%3.2f, %3.2f), (%3.2f, %3.2f)", points->x, points->y, points[1].x, points[1].y, points[2].x, points[2].y);
break;
case kCGPathElementCloseSubpath:
NSLog(@"CloseSubpath (%3.2f, %3.2f)", points->x, points->y);
break;
default:
NSLog(@"unknown");
break;
}
// Add the points if they're available (per type)
if (type != kCGPathElementCloseSubpath)
{
[bezierPoints addObject:VALUE(0)];
if ((type != kCGPathElementAddLineToPoint) &&
(type != kCGPathElementMoveToPoint))
[bezierPoints addObject:VALUE(1)];
}
if (type == kCGPathElementAddCurveToPoint)
[bezierPoints addObject:VALUE(2)];
}
- (NSArray *)pointsFromCGPath:(CGPathRef)path
{
NSMutableArray *points = [NSMutableArray array];
CGPathApply(path, (__bridge void *)points, getPointsFromBezier);
return points;
}
输出将记录到控制台,所有存储在我们开始的 CAShapeLayer 中的路径,输出对于 post 来说太大太乱,但这是开始的样子:
[30146:2680987] MoveToPoint (103.82, 100.00
[30146:2680987] AddLineToPoint (296.75, 100.00)
[30146:2680987] AddLineToPoint (296.75, 144.00)
[30146:2680987] AddLineToPoint (103.82, 144.00)
[30146:2680987] AddCurveToPoint (102.72, 144.00), (102.17, 144.00), (101.67, 143.84)
[30146:2680987] AddLineToPoint (101.58, 143.81)
[30146:2680987] AddCurveToPoint (100.93, 143.58), (100.42, 143.07), (100.19, 142.42)
[30146:2680987] AddCurveToPoint (100.00, 141.83), (100.00, 141.28), (100.00, 140.18)
[30146:2680987] AddLineToPoint (100.00, 103.82)
[30146:2680987] AddCurveToPoint (100.00, 102.72), (100.00, 102.17), (100.16, 101.67)
[30146:2680987] AddLineToPoint (100.19, 101.58)
[30146:2680987] AddCurveToPoint (100.42, 100.93), (100.93, 100.42), (101.58, 100.19)
[30146:2680987] AddCurveToPoint (102.17, 100.00), (102.72, 100.00), (103.82, 100.00)
[30146:2680987] AddLineToPoint (103.82, 100.00)
[30146:2680987] path element in p3: {103.8216625, 100}
[30146:2680987] path element in p3: {296.75, 100}
[30146:2680987] path element in p3: {296.75, 144}
[30146:2680987] path element in p3: {103.8216625, 144}
[30146:2680987] path element in p3: {102.72123239404632, 144}
[30146:2680987] path element in p3: {102.17101736015751, 144}