Як отримати текст у CATextLayer, щоб було зрозуміло


92

Я зробив a CALayerз доданим, CATextLayerі текст виходить розмитим. У документах вони говорять про "згладжування субпікселів", але це не означає для мене багато. Хто-небудь має фрагмент коду, який робить а CATextLayerз трохи чіткого тексту?

Ось текст з документації Apple:

Примітка: CATextLayer вимикає згладжування субпікселів під час відтворення тексту. Текст можна намалювати, використовуючи субпіксельне згладжування, лише коли він компонується на існуючий непрозорий фон одночасно з його растризацією. Немає можливості намалювати текст, згладжений субпікселями, самостійно, будь то зображення або шар, окремо заздалегідь, перш ніж мати фонові пікселі, в які можна вплести пікселі тексту. Встановлення властивості непрозорості шару на ТАК не змінює режим візуалізації.

Друге речення передбачає, що можна отримати гарний текст, якщо compositesйого перетворити на existing opaque background at the same time that it's rasterized. Це чудово, але як мені скласти його і як надати йому непрозорий фон і як його растеризувати?

Код, який вони використовують у своєму прикладі меню кіоску, є таким: (Це OS X, а не iOS, але я припускаю, що це працює!)

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);

EDIT 2: Дивіться мою відповідь нижче про те, як це вирішено. sbg.


Це не відповідь на ваше запитання, але може бути для кого - то як я , хто тільки шукає , щоб зробити приписуваний текст, таким чином , найбільш схожий на використання UILabel: stackoverflow.com/questions/3786528 / ...
DenNukem

Відповіді:


229

Коротка відповідь - Вам потрібно встановити масштабування вмісту:

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

Деякий час тому я дізнався, що коли у вас є власний код малювання, вам потрібно перевірити дисплей сітківки та відповідно масштабувати графіку. UIKitдбає про більшу частину цього, включаючи масштабування шрифту.

Не так з CATextLayer.

Моя розмитість виникла через те, .zPositionщо не дорівнювало нулю, тобто я мав перетворення, застосоване до мого батьківського шару. Встановивши значення нуля, розмитість пішла, і вона була замінена серйозною пікселяцією.

Після пошуку високого і низького рівня я виявив, що ви можете встановити значення .contentsScalea, CATextLayerі ви можете встановити його [[UIScreen mainScreen] scale]відповідно до роздільної здатності екрана. (Я припускаю, що це працює для не сітківки, але я не перевіряв - занадто втомлений)

Після включення цього для мене CATextLayerтекст став чітким. Примітка - це не потрібно для батьківського рівня.

А розмитість? Він повертається, коли ви обертаєтесь у 3D, але ви цього не помічаєте, оскільки текст починається чітким, і поки він рухається, ви не можете сказати.

Проблема вирішена!


37
Це коротка відповідь: textLayer.contentScale = [[UIScreen mainScreen] scale]; BTW, мені теж подобаються довгі відповіді :)
nacho4d

Це стосується будь-якого CALayer, який створюється програмно. Наприклад, якщо ви помітили, що зображення, намальовані на вашому CALayer, не чіткі на дисплеї сітківки, швидше за все, це проблема та рішення.
Джефф Аргаст,

17
Виправлення _textLayer.contentsScale = [[UIScreen mainScreen] scale]; Вам не вистачає "s";)
Ральфлеон,

1
Для мене це не працює. Я додаю CATextLayer до відео (AVFoundation / AVMutableComposition) за допомогою AVVideoCompositionCoreAnimationTool. Текст все ще має псевдонім.
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

Перед налаштуванням слід растеризувати, вам слід:

  1. встановіть rasterizationScale базового шару, який ви збираєтеся растеризувати
  2. встановити властивість contentsScale будь-яких CATextLayers та, можливо, інших типів шарів (це ніколи не заважає це робити)

Якщо ви не зробите # 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

Ви повинні зробити 2 речі, перша була згадана вище:

Розширте 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

Якщо ви прийшли сюди шукати подібну проблему для CATextLayer в OSX, після багатого удару об стіну, я отримав чіткий чіткий текст, виконавши:

text_layer.contentsScale = self.window!.backingScaleFactor

(Я також встановив однаковий вміст фонового шару подання).


0

Це швидше і простіше: вам просто потрібно встановити 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];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.