(我已经在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的调试器预览将提供结果:
我需要这些点作为路径。
首次尝试,使用现代版CGPathCreateCopyByStrokingPath()
let strokedCGPath = bezierPath.cgPath.copy(strokingWithWidth: dotWidth,
lineCap: lineCapStyle,
lineJoin: lineJoinStyle,
miterLimit: 4)
第二次尝试:
let dashedCGPath = bezierPath.cgPath.copy(dashingWithPhase: 0, lengths: dashes)
结果:copy(strokingWithWidth:)
或copy(dashingWithPhase:)
都没有给我完整的路径。
问题:我错过了一些明显的东西吗?有没有办法获得中风的整个路径?
感谢您的帮助。
答案 0 :(得分:2)
[已编辑]
我之前的回答是不正确的。
使用CGPath copy(dashingWithPhase: phase, lengths: pattern)
在这种情况下不起作用。尽管有方法的描述,它实际上不会产生结果笔画的完整轮廓路径。
一个有效的解决方案是:
创建一个临时CGContext
在上下文中,设置所有与笔划相关的参数,例如lineCap
,lineWidth
,lineJoin
,最重要的是,lineDash
将您的路径添加到上下文中:context.addPath(bezierPath.cgPath)
请勿拨打fill()
或stroke()
。我们对绘画不感兴趣。
,请致电context.replacePathWithStrokedPath()
最后,使用let newCGPath = context.path
此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
元素。 “形状”
希望这有助于选择所需的算法。