web-dev-qa-db-ja.com

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

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。

91
Steve

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

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

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

CATextLayer.ではそうではありません

私の不鮮明さは、ゼロではない.zPositionを持っていることに起因しています。つまり、親レイヤーにトランスフォームが適用されていました。これをゼロに設定すると、ぼやけがなくなり、深刻なピクセル化に置き換えられました。

高い値と低い値を検索した後、CATextLayer.contentsScaleを設定でき、画面解像度に合わせて[[UIScreen mainScreen] scale]に設定できることがわかりました。 (私はこれが非網膜で機能すると仮定しますが、私はチェックしていません-あまりにも疲れています)

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

そして不鮮明さ? 3Dで回転しているときに元に戻りますが、テキストがはっきりし始めており、動いている間はわからないため、気づきません。

問題が解決しました!

221
Steve

Swift

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

textLayer.contentsScale = UIScreen.main.scale

前:

enter image description here

後:

enter image description here

32
Suragch

最初に、iOSで質問にタグを付けたことを指摘したかったのですが、制約マネージャーはOSXでしか利用できません。なんとなくシミュレーターで。デバイスでは、この機能は使用できません。

次に、私はCATextLayersを頻繁に作成し、参照しているぼかしの問題がないことを指摘します。一言で言えば、このぼかしは、レイヤー全体をピクセル全体に配置していないために発生します。レイヤーの位置を設定するときは、xとyにfloat値を使用することに注意してください。これらの値に小数点以下の数値がある場合、レイヤーはピクセル全体に配置されないため、このぼかし効果が得られます。その程度は実際の値に依存します。これをテストするには、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値を最も近いピクセル全体に強制するだけで、ぼかしの問題を解決できます。

17
Matt Long

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

  1. ラスタライズするベースレイヤーのrasterizationScaleを設定します
  2. cATextLayersおよびおそらく他のタイプのレイヤーのcontentsScaleプロパティを設定します(実行しても問題ありません)

#1を行わないと、通常のCALayerでさえ、サブレイヤーのRetinaバージョンがぼやけて見えます。

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

次の2つのことを行う必要があります。1つ目は上記のとおりです。

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];
}
4
MoDJ

OSXのCATextLayerで同様の問題を探してここに来た場合、多くの壁にぶつかった後、私は以下を実行することで鮮明なクリアテキストを取得しました。

text_layer.contentsScale = self.window!.backingScaleFactor

(ビューのバックグラウンドレイヤーのcontentScaleも同じに設定します)。

2
james_alvarez

これはより高速で簡単です。contentsScaleを設定するだけです

    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];
0