是否可以从uiview获取所有uibezerpath?

时间:2015-08-20 02:53:33

标签: ios objective-c cgcontext uibezierpath

我一直在研究,但没有找到答案。

如果我使用CGGontext将它绘制到视图中,是否可以从UIView中获取UIVezierPath(UIView)? (如果是的话,你能告诉我怎么做?)UIBezierPath来自用户输入,所以如果用户绘制了大量的UIBezierPath,我需要所有这些路径并将其保存到.svg文件中。

2 个答案:

答案 0 :(得分:3)

这是一个更好的工作示例,在测试了我在提交中给出的一些答案之后,这将是一个将根据您要查找的内容返回一个shapelayers或图层的数组:

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的子层中。事实上,为了进一步扩展这一点,为了您的目的,请参阅以下内容,这将返回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中,输出太大而且很麻烦,不能在这里发布,但是这里的开头是这样的:

  

[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] p3中的路径元素:{103.8216625,100}

     

[30146:2680987] p3中的路径元素:{296.75,100}

     

[30146:2680987] p3中的路径元素:{296.75,144}

     

[30146:2680987] p3中的路径元素:{103.8216625,144}

     

[30146:2680987] p3中的路径元素:{102.72123239404632,144}

     

[30146:2680987] p3中的路径元素:{102.17101736015751,144}

答案 1 :(得分:0)

如果您正在使用Core Graphics绘制路径,那么您可能有一些模型支持drawRect利用的视图以绘制所有路径。如果你不这样做(即你只是更新位图),你应该简单地重构该代码以捕获并保存表示路径所需的信息。