【问题标题】:Antialiasing on CAShapeLayersCAShapeLayers 上的抗锯齿
【发布时间】:2014-03-28 18:24:26
【问题描述】:

我有一个加载指示器的自定义视图,它由多个 CAShapeLayers 组成,我在其上执行各种动画来表示各种状态。在 init 方法中,我创建了许多形状图层并将它们作为子图层添加到视图的图层中。我遇到的问题是我正在绘制的形状边缘非常粗糙,并且似乎没有抗锯齿。我已经从这里的类似答案中尝试了很多东西,但我似乎无法对形状进行抗锯齿处理。之前没遇到过这个问题直接在drawRect画图。

我有什么遗漏或者有更好的方法来完成我想做的事情吗?

更新:以下是绘制形状的比较:

在左侧,我正在使用此代码在layoutSubviews 中绘制:

CGFloat lineWidth = 2.5f;
CGFloat radius = (self.bounds.size.width - lineWidth)/2;
CGPoint center = CGPointMake(CGRectGetWidth(self.frame)/2, CGRectGetHeight(self.frame)/2);

CGFloat startAngle = - ((float)M_PI / 2);
CGFloat endAngle = (2 * (float)M_PI) + startAngle;

UIBezierPath *trackPath =  [UIBezierPath bezierPathWithArcCenter:center
                                                          radius:radius
                                                      startAngle:startAngle
                                                        endAngle:endAngle
                                                       clockwise:YES];
self.trackLayer.path = trackPath.CGPath;
self.trackLayer.lineWidth = lineWidth;

在右侧,我正在从awakeFromNib 调用一个单独的方法:

-(void)awakeFromNib
{
    ....
    self.trackLayer = [self trackShape]
    [self.layer addSublayer:self.trackLayer];
}

-(CAShapeLayer*)trackShape
{
    float start_angle = 2*M_PI*-M_PI_2;
    float end_angle = 2*M_PI*1-M_PI_2;
    float minSize = MIN(self.frame.size.width, self.frame.size.height);
    float radius = (minSize-_strokeWidth)/2 -4;
    CGPoint center = CGPointMake(self.frame.size.width/2,self.frame.size.height/2);
    CAShapeLayer *circle = [CAShapeLayer layer];

    circle.path = [UIBezierPath bezierPathWithArcCenter:center
                                                 radius:radius
                                             startAngle:start_angle
                                               endAngle:end_angle
                                              clockwise:YES].CGPath;
    circle.strokeColor = self.trackColor.CGColor;
    circle.fillColor = nil;
    circle.lineWidth = (_strokeWidth == -1.0) ? minSize * _strokeWidthRatio
    : _strokeWidth;
    circle.rasterizationScale = [[UIScreen mainScreen] scale];

    return circle;
}

【问题讨论】:

  • CAShapeLayer 文档说,“形状将被抗锯齿绘制,并且尽可能在光栅化之前将其映射到屏幕空间以保持分辨率独立性。但是,某些类型的图像处理操作,例如 CoreImage 过滤器,应用于图层或其祖先可能会强制在局部坐标空间中进行光栅化。”每当我添加CAShapeLayer 时,它总是会消除锯齿,所以也许您可以分享您正在做的事情(代码、屏幕快照等),以便我们弄清楚发生了什么。
  • @Rob 我已经更新了截图和代码。
  • 两个圆圈实际上都是抗锯齿的。右边的那个看起来比右边的那个锯齿状,但真的很难说,因为它们的尺寸不同。你能画出完全相同的尺寸吗(并分享你使用的radius 和lineWidth 值)?对于圆圈,radius 中的细微变化(例如 38 与 38.3)会从根本上改变抗锯齿的视觉效果,因此请确保 radius 的值完全相同。
  • 顺便说一句,我发现通过drawRect 中的Core Graphics 调用进行渲染可以提供比CAShapeLayer 技术更好的结果(更平滑、更好的抗锯齿等)。此外,如果您使用CAShapeLayer 技术,我发现半径较小(例如0.5)的阴影和CGSizeZero 的shadowOffset 可以柔化曲线,使其看起来更平滑。跨度>

标签: objective-c core-graphics antialiasing


【解决方案1】:

你提供的图片正是发生在我身上的事。我得到了厚实的圆圈。在我的例子中,代码在 drawRect 方法中。问题是我添加了一个 CAShapeLayer,作为我视图的子层,每次调用 drawRect 时。

因此,对于任何偶然发现类似内容的人,请跟踪您正在添加的 CAShapeLayer 或在再次绘制 drawRect 之前清除所有内容。

【讨论】:

  • 这是我的问题。删除叠加的 CAShapeLayers 会导致边缘不会随着后续的每次重绘而变得锯齿状。谢谢米乔。
猜你喜欢
  • 2014-02-18
  • 1970-01-01
  • 2016-06-28
  • 2011-07-05
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多