【问题标题】:Why is this Core Graphics drawing code generating variating line widths?为什么这个 Core Graphics 绘图代码会生成不同的线宽?
【发布时间】:2012-07-23 18:25:15
【问题描述】:

看图。形状小矩形有不同的线宽。指向大中心矩形的线更粗。以左上角为例:to 线和左边的比右边的和底部的要细。 首先,我虽然这是一种视错觉,但不是。截图是在模拟器上 100% 截取的。

下面用于绘制视图的代码来自UIView子类的DrawRect():

public override void Draw (RectangleF rect)
        {
            rect = this.Bounds;
            CGContext oCtx = UIGraphics.GetCurrentContext();
            oCtx.SetFillColor(UIColor.Clear.CGColor);
            oCtx.ClearRect(rect);

            oCtx.SetLineWidth(2f);

            oCtx.SetFillColor(this.BackgroundColor.CGColor);
            oCtx.SetStrokeColor(this.BackgroundColor.CGColor);
            oCtx.SetAlpha(this.Alpha);

            oCtx.AddRect(new RectangleF(rect.X + HANDLE_WIDTH * 0.5f, rect.Y + HANDLE_HEIGHT * 0.5f, rect.Width - HANDLE_WIDTH, rect.Height - HANDLE_HEIGHT));

            oCtx.FillPath();

            oCtx.SetAlpha(1f);
            oCtx.AddRect(new RectangleF(rect.X, rect.Y, HANDLE_WIDTH, HANDLE_HEIGHT));
            oCtx.AddRect(new RectangleF(rect.Right - HANDLE_WIDTH, rect.Y, HANDLE_WIDTH, HANDLE_HEIGHT));
            oCtx.AddRect(new RectangleF(rect.Right - HANDLE_WIDTH, rect.Bottom - HANDLE_HEIGHT, HANDLE_WIDTH, HANDLE_HEIGHT));
            oCtx.AddRect(new RectangleF(rect.X, rect.Bottom - HANDLE_HEIGHT, HANDLE_WIDTH, HANDLE_HEIGHT));

            oCtx.StrokePath();

#if DEBUG
            oCtx.SetAlpha(0.2f);
            oCtx.SetFillColor(UIColor.DarkGray.CGColor);
            oCtx.AddRect(this.GetMovableArea(rect));
            oCtx.FillPath();
#endif
        }

有人可以解释为什么笔画宽度不同吗?我也尝试改用 StrokeRect() - 结果相同。我什至删除了所有的绘图代码,除了左上角的矩形没有改变。常量 HANDLE_HEIGHT 和 HANDLE_WIDTH 都设置为 20f。

【问题讨论】:

  • 这个问题在真iPad上会出现吗?我认为不会。模拟器很可能没有执行抗锯齿渲染 - 这就是您看到这种效果的原因。

标签: xamarin.ios core-graphics cgcontext


【解决方案1】:

这是由于 CoreGraphics 使用中心笔对齐,例如它将在您指定的线的任一侧绘制像素。正如您已经注意到将坐标带入线宽的一半将修复它。

这篇文章有一个例子,还讨论了 iOS 应用于线路的抗锯齿以及如何避免它。

http://www.raywenderlich.com/2033/core-graphics-101-lines-rectangles-and-gradients

在我们的例子中,路径的边缘是我们想要填充的矩形。因此,当沿该边缘绘制 1 >pixel 线时,线的一半(1/2 像素)将在 >rectangle 的内侧,而线的另一半(1/2 像素)将在外侧>矩形。

当然,因为没有办法绘制 1/2 个像素,Core Graphics 使用抗锯齿来绘制两个像素,而只是使用较浅的阴影来呈现它只有一个像素的外观绘制。

我不认为你可以在 CG 中改变这一点,这与 GDI+ 不同,在 GDI+ 中你可以设置笔对齐http://msdn.microsoft.com/en-us/library/z62ath7a.aspx

【讨论】:

  • 是的,这似乎是本案的原因。
【解决方案2】:

UIViewClipsToBounds 属性的值是多少?

如果 true 则可能是您的问题(2pt 线的一半在边界之外)。

更新

在您的CGContext 上调用GetClipBoundingBox 会返回什么?

【讨论】:

  • 如果我使用该属性不会改变任何东西。但是,如果我在 rect.X + 1 而不是 rect.X 处绘制矩形,则线条是正确的。但是为什么 rect.X (== 0) 会超出剪辑区域!?如果我将线宽设为 1 而不是 2 btw,我也会得到相同的效果。
  • 只是一个快速的猜测 ;-) 我没有用 CG 尝试过,细节因绘图工具包而异。 经常在 0 处绘制 2pt 宽的线通常会从 -1,1(2 pt 宽)创建一个矩形,从 -1,0 可以剪切的部分会显示为你的截图。将线移动到 1(中心)使绘图从 0,2(2 pt 宽)和剪裁内部开始。 1pt 宽的线将是 -0.5,0,5,这也会削减它的一半(剪裁为 0)。
猜你喜欢
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 2020-07-17
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
相关资源
最近更新 更多