CATextLayerのテキストを明確にする方法


92

CALayer追加CATextLayerして作成しましたが、テキストがぼやけて表示されます。ドキュメントでは、「サブピクセルアンチエイリアス」について話していますが、それは私にはあまり意味がありません。誰もCATextLayerが明確なテキストで作るコードスニペットを持っていますか?

Appleのドキュメントのテキストは次のとおりです。

注:CATextLayerは、テキストのレンダリング時にサブピクセルアンチエイリアスを無効にします。テキストは、それがラスタライズされると同時に既存の不透明な背景に合成される場合にのみ、サブピクセルアンチエイリアスを使用して描画できます。テキストピクセルを織り込む背景ピクセルを用意する前に、サブピクセルアンチエイリアスが適用されたテキストを画像またはレイヤーに個別に描画する方法はありません。レイヤーの不透明度プロパティをYESに設定しても、レンダリングモードは変更されません。

2番目の文はcompositesexisting opaque background at the same time that it's rasterized. それを「素晴らしい」テキストにすると見栄えの良いテキストが得られることを意味しますが、どのように合成し、どのように不透明な背景にして、どのようにラスタライズしますか?

彼らがキオスクメニューの例で使用するコードは次のとおりです(iOSではなくOS Xですが、動作すると思います!)

NSInteger i;
for (i=0;i<[names count];i++) {
    CATextLayer *menuItemLayer=[CATextLayer layer];
    menuItemLayer.string=[self.names objectAtIndex:i];
    menuItemLayer.font=@"Lucida-Grande";
    menuItemLayer.fontSize=fontSize;
    menuItemLayer.foregroundColor=whiteColor;
    [menuItemLayer addConstraint:[CAConstraint
         constraintWithAttribute:kCAConstraintMaxY
                      relativeTo:@"superlayer"
                       attribute:kCAConstraintMaxY
                          offset:-(i*height+spacing+initialOffset)]];
    [menuItemLayer addConstraint:[CAConstraint
         constraintWithAttribute:kCAConstraintMidX
                      relativeTo:@"superlayer"
                       attribute:kCAConstraintMidX]];
    [self.menuLayer addSublayer:menuItemLayer];
} // end of for loop 

ありがとう!


編集:実際に使用したコードを追加すると、テキストがぼやけます。それは私が追加について投稿関連する質問からだUILabelのではなくをCATextLayer代わりにブラックボックスを取得します。 http://stackoverflow.com/questions/3818676/adding-a-uilabels-layer-to-a-calayer-and-it-just-shows-black-box

CATextLayer* upperOperator = [[CATextLayer alloc] init];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGFloat components1[4] = {1.0, 1.0, 1.0, 1.0};
CGColorRef almostWhite = CGColorCreate(space,components1);
CGFloat components2[4] = {0.0, 0.0, 0.0, 1.0};
CGColorRef almostBlack = CGColorCreate(space,components2);
CGColorSpaceRelease(space);
upperOperator.string = [NSString stringWithFormat:@"13"];
upperOperator.bounds = CGRectMake(0, 0, 100, 50);
upperOperator.foregroundColor = almostBlack;
upperOperator.backgroundColor = almostWhite;
upperOperator.position = CGPointMake(50.0, 25.0);
upperOperator.font = @"Helvetica-Bold";
upperOperator.fontSize = 48.0f;
upperOperator.borderColor = [UIColor redColor].CGColor;
upperOperator.borderWidth = 1;
upperOperator.alignmentMode = kCAAlignmentCenter;
[card addSublayer:upperOperator];
[upperOperator release];
CGColorRelease(almostWhite);
CGColorRelease(almostBlack);

編集2:これがどのように解決されたかについては、以下の私の答えを参照してください。sbg。


これは、あなたの質問に答えることはありませんが、唯一のUILabelを使用してに最も類似した方法で、起因したテキストを描画するために探している私のような誰かのために関連している可能性がある:stackoverflow.com/questions/3786528/...
DenNukem

回答:


228

短い答え—コンテンツのスケーリングを設定する必要があります。

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

少し前に、カスタム描画コードがある場合、網膜の表示を確認し、それに応じてグラフィックを拡大縮小する必要があることを学びました。 UIKitフォントのスケーリングを含め、これのほとんどを処理します。

そうではない CATextLayer.

私のぼやけ.zPositionは、ゼロではない、つまり、親レイヤーに変換を適用したことによるものです。これをゼロに設定すると、ぼやけがなくなり、深刻なピクセル化に置き換えられました。

高低を検索したところ、.contentsScalea CATextLayerを設定でき[[UIScreen mainScreen] scale]、画面の解像度に合わせて設定できることがわかりました。(これは網膜以外でも機能すると思いますが、チェックしていません-疲れすぎています)

CATextLayerのためにこれを含めた後、テキストはくっきりしたものになりました。注-親レイヤーには必要ありません。

そして、ぼやけ?3Dで回転しているときに戻ってきますが、テキストが最初からはっきりしているので気付かず、動いている間はわかりません。

問題が解決しました!


37
これは短い答えです。textLayer.contentScale = [[UIScreen mainScreen] scale]; ところで、私は長い答えも好きです:)
nacho4d 2012年

これは、プログラムで作成されたすべてのCALayerに適用されます。たとえば、CALayerに描画された画像がRetinaディスプレイで鮮明に表示されない場合は、これが問題と解決策である可能性があります。
Jeff Argast

17
修正_textLayer.contentsScale = [[UIScreen mainScreen] scale]; "s"がありません;)
Ralphleon

1
これは私にはうまくいきません。AVVideoCompositionCoreAnimationToolでCATextLayerをビデオ(AVFoundation / AVMutableComposition)に追加します。テキストにはまだエイリアスがあります。
vietstone

Mac osxにはスケールオプションはありません
Sangram Shivankar

35

迅速

画面と同じ縮尺を使用するようにテキストレイヤーを設定します。

textLayer.contentsScale = UIScreen.main.scale

前:

ここに画像の説明を入力してください

後:

ここに画像の説明を入力してください


macOS swift 4.2バージョン:(NSScreen.main?.backingScaleFactor)!
ロベルト

17

まず、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値を最も近いピクセル全体に強制するだけで、ぼかしの問題を解決できます。


15

shouldRasterizeを設定する前に、次のことを行う必要があります。

  1. ラスタライズするベースレイヤーのrasterizationScaleを設定します。
  2. 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];
}

4

あなたは2つのことをするべきです、最初のものは上で述べられました:

CATextLayerを拡張し、opaqueプロパティとcontentsScaleプロパティを設定してRetinaディスプレイを適切にサポートし、テキストのアンチエイリアスを有効にしてレンダリングします。

+ (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];
}

3

OSXでCATextLayerの同様の問題をここで検索した場合、頭を叩いてから、次のようにしてシャープなテキストを取得しました。

text_layer.contentsScale = self.window!.backingScaleFactor

(ビューの背景レイヤーのcontentScaleも同じに設定しました)。


0

これはより速くて簡単です: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];
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.