使用 CGContext,如何绘制一条以未绘制的虚线段开头的线?

Using CGContext, how to draw a line which starts with an unpainted dash segment?

使用 CGContext,从绘制的线段开始绘制一条虚线很容易:

using (var ctx = UIGraphics.GetCurrentContext())
{
    ctx.BeginPath();
    //... draw a path here
    var pattern = new float[] { 2, 2 };
    ctx.SetLineDash(0, pattern);
    ctx.DrawPath(CGPathDrawingMode.Stroke);
}

这画了一条线,看起来像这样 "xx--xx--xx--xx--",其中 "x" 表示已绘制,“-”表示未绘制。

现在我想画一条线,以未绘制的线段开始,即:“--xx--xx--xx--xx”。有没有一种优雅的方法来实现这一目标?例如。通过告诉 iOS 从未绘制的片段开始?

在我们的示例中,可以使用相位参数实现以未绘制段开始的线:

using (var ctx = UIGraphics.GetCurrentContext())
{
    ctx.BeginPath();
    //... draw a path here
    var pattern = new float[] { 2, 2 };
    ctx.SetLineDash(2, pattern);
    ctx.DrawPath(CGPathDrawingMode.Stroke);
}

然而,对于更复杂的模式(类似于 { 2, 4, 3, 7, 5, 6 }),使用相位参数变得更加麻烦。除了相位参数之外,模式可能还需要移动。

总结:是否可以在不使用相位参数的情况下优雅地创建以未绘制的线段开始的虚线?

注意:代码示例是用 C# (MonoTouch) 编写的,但问题也适用于本机 iOS 代码。

简单的解决方案

仅使用虚线特征,没有相位参数无法解决给定问题。可以通过重新排序破折号数组并设置相位来解决。

要从未绘制的段开始,将最后一个破折号数组条目移到前面,并设置一个具有相同值的阶段。例如。当需要模式 -xx-xx-xx-xx-xx... 时,具有相位 0 的破折号数组 1, 2 将导致像 x--x--x--x--... 这样的模式。根据需要,具有阶段 2 的破折号数组 2, 1 将导致模式 -xx-xx-xx-xx-xx...

具有自适应模式重复的扩展解决方案

似乎iOS总是在绘制和未绘制的段之间交替,并且在重复破折号数组时不会重置。所以例如破折号数组 1, 2, 1 会导致线型看起来像 x--x-xx-x--x...。在我们的例子中,我们希望整个模式重复。也就是说,对于给定的破折号数组,线型应类似于 x--xx--xx--xx....

为此,我们需要确保破折号数组始终具有偶数个元素。除了重新排序破折号数组和设置相位之外,我们还需要调整和删除元素。有四种情况需要考虑。

1.从绘制的段开始,偶数段。

这里无事可做。按原样使用破折号数组。相位为 0.

2。从未绘制的段开始,偶数段。

将最后一个破折号数组条目移到前面,并设置一个具有相同值的相位。参考上面的简单例子。

3。从绘制的段开始,段数为奇数。

将最后一个破折号数组条目添加到第一个条目。删除最后一个条目。设置等于原始最后一个破折号数组条目的相位。

例如破折号数组 1, 2, 1 通常会导致模式 x--x-xx-...。相位为 1 的破折号数组 2, 2 导致所需的模式 x--xx--xx--....

4。从未绘制的段开始,段数为奇数。

将破折号数组的第一个条目添加到最后一个条目。删除第一个条目。将阶段设置为等于所有条目的总和减去原始的第一个破折号数组条目(这实际上让模式开始接近尾声,正是我们将原始第一个条目添加到最后一个条目的位置)。

例如破折号数组 1, 2, 1 通常会导致模式 x--x-xx-...。相位为 3 的模式 2, 2 导致所需的模式 -xx--xx--xx....

备选方案

使用划线功能的替代方案可能是@user2320861 所描述的。 @user2320861 建议使用背景颜色在带有图案线的实线上绘制。当背景颜色已知且使用统一背景时,这应该能很好地工作。

不同背景(例如图像)的变体可以是设置剪贴蒙版(CGContextClipToMask) 通过绘制图案线。然后可以使用此剪贴蒙版绘制实线。