CATextLayer의 텍스트를 명확하게 만드는 방법


92

CALayer추가 로 만들었는데 CATextLayer텍스트가 흐릿하게 나옵니다. 문서에서 그들은 "서브 픽셀 앤티 앨리어싱"에 대해 이야기하지만 나에게는 그다지 의미가 없습니다. 누구든지 CATextLayer명확한 텍스트로 만드는 코드 스 니펫이 있습니까?

다음은 Apple 문서의 텍스트입니다.

참고 : CATextLayer는 텍스트를 렌더링 할 때 하위 픽셀 앤티 앨리어싱을 비활성화합니다. 텍스트는 래스터 화되는 동시에 기존의 불투명 한 배경으로 합성되는 경우에만 하위 픽셀 앤티 앨리어싱을 사용하여 그릴 수 있습니다. 텍스트 픽셀을 짜는 배경 픽셀을 갖기 전에 별도로 하위 픽셀 앤티 앨리어싱 된 텍스트를 이미지 또는 레이어에 따로 그릴 수있는 방법은 없습니다. 레이어의 불투명도 속성을 YES로 설정해도 렌더링 모드가 변경되지 않습니다.

두 번째 문장 compositesexisting opaque background at the same time that it's rasterized. That 's great로 만들면보기 좋은 텍스트를 얻을 수 있음을 의미합니다 . 그러나 어떻게 합성하고 불투명 한 배경을 제공하고 어떻게 래스터 화합니까?

키오스크 메뉴의 예에서 사용하는 코드는 다음과 같습니다. (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(A)보다 다소을 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.

내 흐릿함은 .zPosition0이 아닌, 즉 부모 레이어에 변형을 적용했기 때문에 발생했습니다. 이 값을 0으로 설정하면 흐릿함이 사라지고 심각한 픽셀 화로 대체되었습니다.

높고 낮게 검색 한 결과 .contentsScalea CATextLayer를 설정할 수 [[UIScreen mainScreen] scale]있고 화면 해상도와 일치하도록 설정할 수 있다는 것을 알았 습니다. (나는 이것이 비 망막에서 작동한다고 가정하지만 확인하지 않았습니다-너무 피곤합니다)

이것을 포함시킨 후 CATextLayer텍스트가 선명 해졌습니다. 참고-상위 레이어에는 필요하지 않습니다.

그리고 흐릿함? 3D로 회전 할 때 다시 나타나지만 텍스트가 명확하게 시작하고 움직이는 동안에는 알 수 없기 때문에 눈치 채지 못합니다.

문제 해결됨!


37
이것은 짧은 대답입니다 : textLayer.contentScale = [[UIScreen mainScreen] scale]; BTW, 나는 긴 답변처럼 너무 :)
nacho4d

이것은 프로그래밍 방식으로 생성 된 모든 CALayer에 적용됩니다. 예를 들어 CALayer에 그려진 이미지가 레티 나 디스플레이에서 선명하지 않다는 것을 알게된다면 이것이 문제와 해결책 일 가능성이 높습니다.
제프 Argast

17
수정 _textLayer.contentsScale = [[UIScreen mainScreen] scale]; "s"가 누락되었습니다.)
Ralphleon

1
이것은 나를 위해 작동하지 않습니다. AVVideoCompositionCoreAnimationTool에서 비디오 (AVFoundation / AVMutableComposition)에 CATextLayer를 추가합니다. 텍스트에는 여전히 앨리어싱이 있습니다.
vietstone

맥 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 및 가능한 다른 유형의 레이어의 contentsScale 속성을 설정합니다.

# 1을 수행하지 않으면 일반 CALayers에서도 하위 레이어의 레티 나 버전이 흐릿하게 보입니다.

- (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

두 가지 작업을 수행해야합니다. 첫 번째 작업은 위에서 언급했습니다.

CATextLayer를 확장하고 opaque 및 contentsScale 속성을 설정하여 망막 디스플레이를 올바르게 지원 한 다음 텍스트에 대해 안티 앨리어싱을 활성화하여 렌더링합니다.

+ (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

(또한 뷰 배경 레이어 contentsScale을 동일하게 설정했습니다).


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.