如何沿路径/ BezierCurve创建多个UIButton? [英] How to create several UIButtons along a path/BezierCurve?

查看:99
本文介绍了如何沿路径/ BezierCurve创建多个UIButton?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何沿路径/ BezierCurve创建对象?换句话说,如何沿着给定路径创建多个UIButton,沿同一路径给定间隔?

How can I create objects along a path/BezierCurve? In other words, how can I create several UIButtons along a given path, with a given interval along that same path?

我已经看到了很多关于移动对象的问题。但我需要一个实际创建它们的解决方案。

I have seen dozens of questions about moving objects. But I need a solution to actually create them.

我想沿着路径前进并为每个X点/距离创建一个对象。像这样:

I would like to go along the path and create an object for every X points/distance. Like this:

....@....@....@....@....

在这种情况下,每4个点获得一个位置,并在那里创建一个UIButton。 / p>

In this case, for every 4 points, get the position, and create a UIButton there.

推荐答案

iOS没有直接为您提供沿路径间隔的点的公共API。但是有一种迂回的方式来做到这一点。假设您希望路径上的点之间的距离为X.

iOS doesn't have a public API that directly gives you points spaced along a path. But there is a roundabout way to do it. Suppose you want points along the path spaced a distance of X apart.

首先,创建一个包含路径的 CGPathRef 。 (如果您愿意,可以构建 UIBezierPath ,然后获取其 CGPath 属性。)

First, create a CGPathRef containing your path. (You can construct a UIBezierPath if you prefer and then gets its CGPath property.)

然后,使用 {X,X} 的短划线模式调用 CGPathCreateCopyByDashingPath 。例如:

Then, call CGPathCreateCopyByDashingPath, using a dash pattern of { X, X }. For example:

static CGFloat const kSpace = 10;
CGPathRef dashedPath = CGPathCreateCopyByDashingPath(path, NULL, 0,
    (CGFloat const []){ kSpace, kSpace }, 2);

这将返回包含多个子路径的新路径。每个子路径是原始路径的长度X段,并且沿着原始路径与其相邻子路径隔开X的距离。因此,子路径的端点沿着原始路径以长度X的间隔隔开。

This returns a new path containing multiple subpaths. Each subpath is a length X segment of the original path, and is separated from its neighboring subpaths by a distance of X along the original path. Thus the endpoints of the subpaths are spaced along the original path at an interval of length X.

因此,最后,使用 CGPathApply枚举虚线路径,选择端点并在那里创建按钮。首先,你需要将它包装在一个带块的函数中:

So, finally, enumerate the dashed path using CGPathApply, picking the endpoints and creating buttons there. First, you'll want to wrap it in a function that takes a block:

static void applyBlockToPathElement(void *info, const CGPathElement *element) {
    void (^block)(const CGPathElement *) = (__bridge void (^)(const CGPathElement *))(info);
    block(element);
}

void MyCGPathApplyBlock(CGPathRef path, void (^block)(const CGPathElement *element)) {
    CGPathApply(path, (__bridge void *)(block), applyBlockToPathElement);
}

然后你可以应用一个找到每个子路径端点的块并创建一个按钮那里。假设你有一个名为 createButtonAtPoint:的方法,这样的东西应该有效:

Then you can apply a block that finds the each subpath endpoint and creates a button there. Assuming you have a method named createButtonAtPoint:, something like this should work:

__block BOOL isInSubpath = NO;
__block CGPoint subpathStart = CGPointZero;
__block CGPoint currentPoint = CGPointZero;
MyCGPathApplyBlock(dashedPath, ^(const CGPathElement *element) {
    switch (element->type) {
        case kCGPathElementMoveToPoint:
            if (isInSubpath) {
                [self createButtonAtPoint:currentPoint];
                isInSubpath = NO;
            }
            currentPoint = element->points[0];
            break;

        case kCGPathElementCloseSubpath:
            // This should not appear in a dashed path.
            break;

        case kCGPathElementAddLineToPoint:
        case kCGPathElementAddQuadCurveToPoint:
        case kCGPathElementAddCurveToPoint:
            if (!isInSubpath) {
                [self createButtonAtPoint:currentPoint];
                isInSubpath = YES;
            }
            int pointIndex =
                element->type == kCGPathElementAddLineToPoint ? 0
                : element->type == kCGPathElementAddQuadCurveToPoint ? 1
                : /* element->type == kCGPathElementAddCurveToPoint ? */ 2;
            currentPoint = element->points[pointIndex];
            break;
    }
});

这篇关于如何沿路径/ BezierCurve创建多个UIButton?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆