如何使CATextLayer中的文本清晰

如何使CATextLayer中的文本清晰,text,ios,core-animation,calayer,Text,Ios,Core Animation,Calayer,我用添加的CATextLayer制作了一个CALayer,文本变得模糊。在文档中,他们谈到了“亚像素抗锯齿”,但这对我来说意义不大。有没有人有一个代码片段,可以用一点清晰的文本制作一个CATextLayer 以下是苹果公司文档中的文字: 注意:CATextLayer在渲染文本时禁用亚像素抗锯齿。 仅当文本处于禁用状态时,才能使用亚像素抗锯齿绘制文本 同时合成到现有不透明背景中 它是光栅化的。无法通过以下方式绘制亚像素抗锯齿文本: 它本身,无论是进入一个图像还是一个层,都是在 具有将文本像素编织成

我用添加的
CATextLayer
制作了一个
CALayer
,文本变得模糊。在文档中,他们谈到了“亚像素抗锯齿”,但这对我来说意义不大。有没有人有一个代码片段,可以用一点清晰的文本制作一个
CATextLayer

以下是苹果公司文档中的文字:

注意:CATextLayer在渲染文本时禁用亚像素抗锯齿。 仅当文本处于禁用状态时,才能使用亚像素抗锯齿绘制文本 同时合成到现有不透明背景中 它是光栅化的。无法通过以下方式绘制亚像素抗锯齿文本: 它本身,无论是进入一个图像还是一个层,都是在 具有将文本像素编织成的背景像素。背景 图层的“不透明度”属性为“是”不会更改渲染 模式

第二句话意味着,如果一个
在光栅化的同时将它合成成一个
现有的不透明背景,就可以得到好看的文本。
这很好,但是我如何合成它,如何给它一个不透明背景,如何光栅化它

他们在Kiosk菜单示例中使用的代码如下:(它是OSX,不是iOS,但我认为它可以工作!)



编辑2:请参阅下面我的答案,了解这是如何解决的。sbg.

首先,我想指出的是,您已经用iOS标记了您的问题,但约束管理器仅在OSX上可用,因此我不确定您如何使其工作,除非您能够在模拟器中以某种方式链接到它。在设备上,此功能不可用

接下来,我要指出的是,我经常创建CATextLayers,从来没有你提到的模糊问题,所以我知道这是可以做到的。简而言之,之所以会出现这种模糊,是因为您没有在整个像素上定位图层。请记住,当设置图层的位置时,对x和y使用浮点值。如果这些值在小数点后有数字,则图层将不会定位在整个像素上,因此会产生这种模糊效果——模糊程度取决于实际值。要测试这一点,只需创建一个CATextLayer并将其显式添加到层树中,确保您的位置参数位于整个像素上。例如:

CATextLayer *textLayer = [CATextLayer layer];
[textLayer setBounds:CGRectMake(0.0f, 0.0f, 200.0f, 30.0f)];
[textLayer setPosition:CGPointMake(200.0f, 100.0f)];
[textLayer setString:@"Hello World!"];

[[self menuLayer] addSublayer:textLayer];

如果你的文字仍然模糊不清,那么还有其他问题。文本层上的模糊文本是错误编写代码的产物,而不是该层的预期功能。将层添加到父层时,您只需将x和y值强制设置为最接近的整像素,就可以解决模糊问题。

简短回答-您需要设置内容缩放:

textLayer.contentsScale = [[UIScreen mainScreen] scale];

不久前,我了解到,当您有自定义绘图代码时,您必须检查视网膜显示并相应地缩放图形
UIKit
处理了大部分问题,包括字体缩放

而CATextLayer则不然。

我的模糊度来自于一个不是零的
.zPosition
,也就是说,我对父层应用了一个变换。通过将其设置为零,模糊度消失,取而代之的是严重的像素化

在上下搜索之后,我发现您可以为
CATextLayer
设置
.contentsScale
,并将其设置为
[[UIScreen mainScreen]缩放]
以匹配屏幕分辨率。(我想这对非视网膜有效,但我没有检查-太累了)

在为my
CATextLayer
添加此内容后,文本变得清晰。注意-父层不需要这样做

那模糊呢?当你在3D中旋转时,它会回来,但是你没有注意到它,因为文本开始时很清晰,当它运动时,你无法分辨


问题解决了

在设置应光栅化之前,您应该:

  • 设置要栅格化的基础层的栅格化比例
  • 设置任何CATextLayers和其他类型的层的ContentsCale属性(这样做不会有任何伤害)
  • 如果你不做#1,那么视网膜版本的子层将看起来模糊,即使是对于正常的Calayer

    - (void)viewDidLoad {
      [super viewDidLoad];
    
      CALayer *mainLayer = [[self view] layer];
      [mainLayer setRasterizationScale:[[UIScreen mainScreen] scale]];
    
      CATextLayer *messageLayer = [CATextLayer layer];
      [messageLayer setForegroundColor:[[UIColor blackColor] CGColor]];
      [messageLayer setContentsScale:[[UIScreen mainScreen] scale]];
      [messageLayer setFrame:CGRectMake(50, 170, 250, 50)];
      [messageLayer setString:(id)@"asdfasd"];
    
      [mainLayer addSublayer:messageLayer];
    
      [mainLayer setShouldRasterize:YES];
    }
    

    你应该做两件事,第一件是上面提到的:

    扩展CATextLayer并设置不透明和ContentsCale属性以正确支持视网膜显示,然后对文本启用抗锯齿进行渲染

    + (TextActionLayer*) layer
    {
      TextActionLayer *layer = [[TextActionLayer alloc] init];
      layer.opaque = TRUE;
      CGFloat scale = [[UIScreen mainScreen] scale];
      layer.contentsScale = scale;
      return [layer autorelease];
    }
    
    // Render after enabling with anti aliasing for text
    
    - (void)drawInContext:(CGContextRef)ctx
    {
        CGRect bounds = self.bounds;
        CGContextSetFillColorWithColor(ctx, self.backgroundColor);
        CGContextFillRect(ctx, bounds);
        CGContextSetShouldSmoothFonts(ctx, TRUE);
        [super drawInContext:ctx];
    }
    

    如果您来这里搜索OSX中CATextLayer的类似问题,在经历了多次墙击之后,我通过以下操作获得了清晰的文本:

    text_layer.contentsScale = self.window!.backingScaleFactor
    

    (我还将视图背景层内容比例设置为相同)

    这更快更容易:只需设置ContentsCale即可

        CATextLayer *label = [[CATextLayer alloc] init];
        [label setFontSize:15];
        [label setContentsScale:[[UIScreen mainScreen] scale]];
        [label setFrame:CGRectMake(0, 0, 50, 50)];
        [label setString:@"test"];
        [label setAlignmentMode:kCAAlignmentCenter];
        [label setBackgroundColor:[[UIColor clearColor] CGColor]];
        [label setForegroundColor:[[UIColor blackColor] CGColor]];
        [self addSublayer:label];
    
    敏捷的 将文本层设置为使用与屏幕相同的比例

    textLayer.contentsScale = UIScreen.main.scale
    
    之前:

    之后:

    这是简短的回答:
    textLayer.contentScale=[[UIScreen mainScreen]scale]顺便说一句,我也喜欢长答案:)这适用于任何通过编程创建的CALayer。例如,如果您注意到绘制到CALayer中的图像在视网膜显示上不清晰,则很可能这就是问题和解决方案您缺少一个“s”;)这对我不管用。我通过AVVideoCompositionCoreAnimationTool将CATextLayer添加到视频(AVFoundation/AVMutableComposition)。文本仍然有别名。mac OSX中没有缩放选项。这不会回答您的问题,但可能与像我这样只希望绘制属性文本的人有关,其方式与使用UILabel:macOS swift 4.2版本最为相似:(NSScreen.main?.backingScaleFactor)@罗伯托,不要强行打开!安全的解决方案是:
    textLayer.contentsScale=NSScreen.main?.backingScaleFactor??textLayer.contentsCale
        CATextLayer *label = [[CATextLayer alloc] init];
        [label setFontSize:15];
        [label setContentsScale:[[UIScreen mainScreen] scale]];
        [label setFrame:CGRectMake(0, 0, 50, 50)];
        [label setString:@"test"];
        [label setAlignmentMode:kCAAlignmentCenter];
        [label setBackgroundColor:[[UIColor clearColor] CGColor]];
        [label setForegroundColor:[[UIColor blackColor] CGColor]];
        [self addSublayer:label];
    
    textLayer.contentsScale = UIScreen.main.scale