作为路径的Stroked UIBezierPath / CGPath的iOS概要

时间:2017-10-31 01:23:46

标签: ios swift core-graphics uibezierpath cgpath

(我已经在SO上阅读了其他答案,但它们似乎并没有解决手头的问题。)

[Swift 4,Xcode 9]

我需要获得表示路径stroke()之后的绘制区域的路径。即表示笔画轮廓的路径。

给定UIBezierPath具有以下属性:

let dotWidth: CGFloat = 3
let spacing: CGFloat = 12
let dashes: [CGFloat] = [0.0, spacing]
let lineCapStyle: CGLineCap = .round
let lineJoinStyle: CGLineJoin = .miter
bezierPath.lineCapStyle = lineCapStyle
bezierPath.lineJoinStyle = lineJoinStyle
bezierPath.setLineDash(dashes, count: dashes.count, phase: 0)
bezierPath.lineWidth = dotWidth

Xcode的调试器预览将提供结果:

enter image description here

我需要这些点作为路径。

首次尝试,使用现代版CGPathCreateCopyByStrokingPath()

let strokedCGPath = bezierPath.cgPath.copy(strokingWithWidth: dotWidth,
    lineCap: lineCapStyle,
    lineJoin: lineJoinStyle,
    miterLimit: 4)

enter image description here

第二次尝试:

let dashedCGPath = bezierPath.cgPath.copy(dashingWithPhase: 0, lengths: dashes)

enter image description here

结果:copy(strokingWithWidth:)copy(dashingWithPhase:)都没有给我完整的路径。

问题:我错过了一些明显的东西吗?有没有办法获得中风的整个路径?

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

[已编辑]

我之前的回答是不正确的。

使用CGPath copy(dashingWithPhase: phase, lengths: pattern)在这种情况下不起作用。尽管有方法的描述,它实际上不会产生结果笔画的完整轮廓路径。

一个有效的解决方案是:

  • 创建一个临时CGContext

  • 在上下文中,设置所有与笔划相关的参数,例如lineCaplineWidthlineJoin,最重要的是,lineDash

    < / LI>
  • 将您的路径添加到上下文中:context.addPath(bezierPath.cgPath)

  • 请勿拨打fill()stroke()。我们对绘画不感兴趣。

  • ,请致电context.replacePathWithStrokedPath()

  • 最后,使用let newCGPath = context.path

  • 将新的cgPath拉出上下文

newCGPath将是描边路径的轮廓,就像它已被绘制一样。

答案 1 :(得分:0)

您也可以将两者结合起来。应该提供您想要的效果。

let dashedCGPath = bezierPath.cgPath
    .copy(dashingWithPhase: 0, lengths: dashes)
    .copy(strokingWithWidth: dotWidth, lineCap: lineCapStyle, lineJoin: lineJoinStyle, miterLimit: 4)

答案 2 :(得分:0)

由于此处讨论了两种不同的算法,因此让我来说明一下区别:

struct NodeMap
{
    object items; // null, Node or sorted List<Node>
    public IEnumerable<Node> Items => items is Node node ? new[] { node } : items as IEnumerable<Node>;
    public bool TryGetItem(char key, out Node item, bool create = false)
    {
        item = null;
        if (items == null)
        {
            if (create) items = item = new Node(key);
        }
        else if (items is Node node)
        {
            if (node.Key == key) item = node;
            else if (create) items = node.Key < key ? new List<Node>(2) { node, (item = new Node(key)) } : new List<Node>(2) { (item = new Node(key)), node };
        }
        else
        {
            var nodeList = (List<Node>)items;
            int lo = 0, hi = nodeList.Count - 1;
            while (lo <= hi)
            {
                int mid = lo + ((hi - lo) >> 1);
                node = nodeList[mid];
                if (node.Key == key) { item = node; break; }
                if (node.Key < key) lo = mid + 1; else hi = mid - 1;
            }
            if (item == null && create) nodeList.Insert(lo, item = new Node(key));
        }
        return item != null;
    }
}

将一维折线创建为每个破折号闭合的子路径。它们不包含cgPath.copy(dashingWithPhase: phase, lengths: pattern) 元素。 “中风”

另一方面

closeSubpath

为每个破折号创建二维封闭的多边形作为子路径。它们确实包含context.replacePathWithStrokedPath() let newCGPath = context.path 元素。 “形状”

希望这有助于选择所需的算法。