1

几个小时以来,我一直在努力解决这个问题。我试着阅读并寻找答案。我什至尝试过“走开,然后再回来”的方法,但没有奏效。我什至尝试过瑜伽和冥想!我没有占上风。。

所以请各位高手赐教。

我只是想获得不在drawRect内的CGPath副本:

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, ......);
CGPathAddLineToPoint(path, ....);
CGPathAddLineToPoint(path, ....);
CGPathAddLineToPoint(path, ....);
CGPathAddLineToPoint(path, ....);

最后: 那没有用,所以我也尝试使用而不是上面的 2 个调用: 最终 - 我只是希望能够获取此路径并将其作为路径插入 CAShapeLayer 并通过进行此调用为其设置动画:
CGPathCloseSubpath(path);
CGContextAddPath(context, path);
CGPathCreateMutableCopy(path);

animation.toValue = [UIBezierPath bezierPathWithCGPath:path];

因此,在我尝试进行另一项放松活动(例如不带降落伞的跳伞)之前,希望能理清思路并最终做到这一点,您能帮我举几个例子吗?除此之外,您能否向我详细解释使用以下功能的正确方法:

CGPathCloseSubpath(path);
CGContextAddPath(context, path);
CGPathCreateMutableCopy(path);

提前致谢。

4

1 回答 1

0
  • CGPath 是具有 C 风格 API 的 C 风格数据结构。基本上它是组成路径的点列表。

  • CGContext 也是一种用于绘制图像的 C 风格数据结构(可能大一点),即将点转换为彩色像素。

我将我的片段放入一个函数中,您可以简单地将其复制并粘贴到单个屏幕 xcode 项目中。您会在代码中找到解释作为注释,以及用于深入调试和探索 CGPath 对象的两个函数(我从https://github.com/erica/iOS-6-Cookbook获取并添加了一些内容)。

#import "ViewController.h"
#import "OverlayView.h"
#import <QuartzCore/QuartzCore.h>

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // create a graphics context with the C-API of the QuartzCore framework
    // the graphics context is only required for drawing the path
    CGRect compositionBounds = CGRectMake(30, 30, 300, 508);
    UIGraphicsBeginImageContext(compositionBounds.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // create a mutable path with QuartzCore
    CGMutablePathRef p1 = CGPathCreateMutable();

    // create a CGPath with UIKit classes using Obj-C
    UIBezierPath *bp = [UIBezierPath bezierPath];
    [bp moveToPoint:(CGPoint){180, 120}];
    [bp addLineToPoint:(CGPoint){30, 170}];
    [bp addLineToPoint:(CGPoint){135, 175}];
    [bp addLineToPoint:(CGPoint){105, 115}];
    // if you fill the path during drawing it gets closed implicitly
//    [bp closePath];
    // add the CGPath to our mutable path
    CGPathAddPath(p1, nil, bp.CGPath);

    // add a closed triangle as subpath to our mutable path
    CGPathMoveToPoint(p1, nil, 50, 250);
    CGPoint p2[3];
    p2[0] = CGPointMake(10, 20);
    p2[1] = (CGPoint){210, 50};
    p2[2] = (CGPoint){80, 120};
    CGPathAddLines(p1, nil, p2, 3);
    // explicitly close our last added subpath
    CGPathCloseSubpath(p1);

    // draw our mutable path (with all its subpaths) filling its area
    CGContextAddPath(ctx, p1);
    CGContextSetFillColorWithColor(ctx, [[UIColor redColor] CGColor]);
    CGContextFillPath(ctx);

    // draw our mutable path (with all its subpaths) stroking its outline
    CGContextAddPath(ctx, p1);
    CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 1.0);
    CGContextStrokePath(ctx);

    // display our mutable path in an image view on screen
    UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
    UIImageView *iv = [[UIImageView alloc] initWithImage:i];
    [self.view addSubview:iv];
    iv.frame = self.view.frame;

    // release ressources created with the C-API of QuartzCore
    CGPathRelease(p1);
    UIGraphicsEndImageContext();

    // create a mutable copy of a path and don't use it for drawing
    CGMutablePathRef p3 = CGPathCreateMutableCopy(bp.CGPath);
    NSArray *p3points = [self pointsFromCGPath:p3];
    for (NSValue *point in p3points) {
        NSLog(@"path element in p3: %@", NSStringFromCGPoint(point.CGPointValue));
    }
    // note that UIBezierPath takes care of its path itself
    CGPathRelease(p3);

}

// modified from https://github.com/erica/iOS-6-Cookbook

#define VALUE(_INDEX_) [NSValue valueWithCGPoint:points[_INDEX_]]

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;
}
于 2013-06-20T08:10:41.943 回答