NSBezierPath绘图

14

我想在一个NSImage上绘制一个圆角矩形轮廓,我想使用NSBezierPath是最好的方式。然而,我遇到了一个问题:没有画出好看的曲线,而是得到了这个:

enter image description here

由于我无法理解的原因,NSBezierPath绘制的圆弧部分颜色比其余部分暗。

这是我正在使用的代码(在自定义视图的drawRect:调用内部):

NSBezierPath* bp = [NSBezierPath bezierPathWithRoundedRect: self.bounds xRadius: 5 yRadius: 5];
[[[NSColor blackColor] colorWithAlphaComponent: 0.5] setStroke];
[bp stroke];

有什么想法吗?

编辑:

如果我将路径向内缩小0.5,所有内容都会绘制得很好。但是如果我将路径偏移10像素(例如),为什么会出现这种情况呢?

enter image description here

如果我理解正确的话,它也应该绘制一条细线...


关键是至少插入0.5。这将使您远离剪辑矩形的边缘。您可以进一步移动,距离边缘更远,但不会产生任何额外效果。 - Wade Tregaskis
我知道,但似乎如果我插入0.5以上的值,线条会变得更粗,而我不明白为什么。它应该像插入0.5那样准确地绘制。 - Alex
2
和答案解释的原因相同 - 当您插入10.0时,您跨越了像素的行(或列),因此您会得到一个两个像素宽的灰线,而不是一个像素宽的黑线。尝试通过9.5或10.5进行插入,以查看差异。 - Wade Tregaskis
2个回答

60

许多渲染系统都源自于PostScript绘图模型,其中Core Graphics是这些派生系统之一。(以下是其他一些:PDF、SVGHTML Canvas 2D ContextCairo)。

所有这些系统都有一个将路径用固定宽度的线条描边的概念。当你描边路径时,线条横跨在路径上,线条宽度的一半在路径的一侧,另一半在路径的另一侧。下面的图表可能更清楚地说明了这一点:

stroked path, unclipped

现在,当您描绘沿视图边界的路径时会发生什么?描边的一半落在视图范围之外并被剪裁掉 - 并没有绘制出来。只有落在视图范围内的描边的一半才能看到。

当您使用圆角时,该角从视图边界向其中心拉开,因此围绕圆角的描边更多地落在视图范围内。因此,描边在圆角周围看起来变得更粗,如下所示:

stroked path, clipped

为了解决这个问题,您需要将路径嵌入线条宽度的一半,以便整个描边沿着整个路径都落在视图范围内。默认的线宽是1.0,因此:

NSBezierPath* bp = [NSBezierPath bezierPathWithRoundedRect:
    NSRectInset(self.bounds, 0.5, 0.5) xRadius:5 yRadius:5];

终于我也得到了这个令人惊讶的事实... 谢谢 Rob :) - Anoop Vaidya
那是一个惊人的答案。谢谢你。我还有一个问题,与你的解决方案有关。你能看一下吗? - Alex
只有你发布了它,我才能看到。 - rob mayoff
2
100万小时,只有你能够引起我的注意:“一半的笔画将超出您视图的边界并被裁剪掉 - 不会被绘制”。没有其他人明确说明这一点,而我在知道笔画跨越路径后太蠢了,无法建立这种联系。如果可以的话,我会加100分,但我只能加1分。 - A'sa Dickens
太棒了的答案。谢谢! - Warpling

0
在iOS领域中,只需减去圆的半径以防止被剪裁。
UIBezierPath *roundPath = [UIBezierPath bezierPath];
[roundPath addArcWithCenter:
CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)
 radius:(self.frame.size.width / 2 - 0.5) 
startAngle:M_PI_2 endAngle:M_PI * 3 / 2.f clockwise:YES];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接