Zrobiłem CALayer
z dodatkiem CATextLayer
i tekst jest rozmyty. W dokumentach mówią o „antyaliasingu subpikselowym”, ale to niewiele dla mnie znaczy. Czy ktoś ma fragment kodu, który tworzy fragment CATextLayer
tekstu, który jest jasny?
Oto tekst z dokumentacji Apple:
Uwaga: CATextLayer wyłącza antyaliasing podpikselowy podczas renderowania tekstu. Tekst można narysować za pomocą antyaliasingu subpikselowego tylko wtedy, gdy jest on wkomponowany w istniejące nieprzezroczyste tło w tym samym czasie, gdy jest rasteryzowany. Nie ma możliwości samodzielnego narysowania tekstu z antyaliasem subpikselowym, czy to na obrazie, czy w warstwie, osobno, zanim piksele tła zostaną wplecione w piksele tekstu. Ustawienie właściwości krycia warstwy na TAK nie zmienia trybu renderowania.
Drugie zdanie sugeruje, że można uzyskać dobrze wyglądający tekst, jeśli połączymy composites
go w existing opaque background at the same time that it's rasterized.
To świetnie, ale jak go złożyć i jak nadać mu nieprzezroczyste tło i jak go rasteryzować?
Kod, którego używają w swoim przykładzie menu kiosku, jest taki: (To OS X, a nie iOS, ale zakładam, że działa!)
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
Dzięki!
EDYCJA: Dodanie kodu, którego faktycznie użyłem, spowodowało rozmyty tekst. Jest to z pokrewnego pytania, które opublikowałem, aby dodać UILabel
zamiast a, CATextLayer
ale zamiast tego uzyskać czarne pudełko. 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);
EDYCJA 2: Zobacz moją odpowiedź poniżej, aby dowiedzieć się, jak to zostało rozwiązane. sbg.
źródło
Odpowiedzi:
Krótka odpowiedź - należy ustawić skalowanie zawartości:
textLayer.contentsScale = [[UIScreen mainScreen] scale];
Jakiś czas temu dowiedziałem się, że kiedy masz niestandardowy kod rysowania, musisz sprawdzić wyświetlacz siatkówki i odpowiednio skalować swoją grafikę.
UIKit
zajmuje się większością z tego, łącznie ze skalowaniem czcionek.Nie tak z
CATextLayer.
Moje rozmycie wynikało z posiadania wartości
.zPosition
różnej od zera, to znaczy, że na warstwie macierzystej zastosowano transformację. Po ustawieniu tego na zero rozmycie zniknęło i zostało zastąpione poważną pikselacją.Po wyszukaniu wysokich i niskich stwierdziłem, że możesz ustawić
.contentsScale
aCATextLayer
i możesz ustawić to,[[UIScreen mainScreen] scale]
aby pasowało do rozdzielczości ekranu. (Zakładam, że to działa dla innych niż siatkówka, ale nie sprawdziłem - zbyt zmęczony)Po uwzględnieniu tego dla mojego
CATextLayer
tekstu stał się wyraźny. Uwaga - nie jest to konieczne dla warstwy macierzystej.A rozmycie? Wraca, gdy obracasz się w 3D, ale nie zauważasz tego, ponieważ tekst zaczyna się wyraźny, a gdy jest w ruchu, nie możesz tego stwierdzić.
Problem rozwiązany!
źródło
textLayer.contentScale = [[UIScreen mainScreen] scale];
_textLayer.contentsScale = [[UIScreen mainScreen] scale];
Brakuje "s";)Szybki
Ustaw warstwę tekstową tak, aby używała tej samej skali co ekran.
textLayer.contentsScale = UIScreen.main.scale
Przed:
Po:
źródło
Po pierwsze, chciałem zaznaczyć, że oznaczyłeś swoje pytanie tagiem iOS, ale menedżery ograniczeń są dostępne tylko w systemie OSX, więc nie jestem pewien, jak to działa, chyba że udało Ci się połączyć z tym jakoś w symulatorze. Na urządzeniu ta funkcja nie jest dostępna.
Następnie zaznaczę tylko, że często tworzę CATextLayers i nigdy nie mam problemu z rozmyciem, do którego się odnosisz, więc wiem, że można to zrobić. Krótko mówiąc, to rozmycie występuje, ponieważ nie ustawiasz warstwy na całym pikselu. Pamiętaj, że kiedy ustawiasz położenie warstwy, używasz wartości zmiennoprzecinkowych dla x i y. Jeśli wartości te mają liczby po przecinku, warstwa nie zostanie umieszczona na całym pikselu, co spowoduje efekt rozmycia, którego stopień zależy od rzeczywistych wartości. Aby to przetestować, po prostu utwórz CATextLayer i jawnie dodaj ją do drzewa warstw, upewniając się, że parametr pozycji dotyczy całego piksela. Na przykład:
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];
Jeśli tekst jest nadal niewyraźny, oznacza to, że coś jest nie tak. Zamazany tekst na warstwie tekstowej jest artefaktem nieprawidłowo napisanego kodu, a nie zamierzoną funkcją warstwy. Dodając warstwy do warstwy nadrzędnej, możesz po prostu przekształcić wartości xiy do najbliższego całego piksela, co powinno rozwiązać problem z rozmyciem.
źródło
Przed ustawieniem shouldRasterize należy:
Jeśli tego nie zrobisz # 1, wersja warstw podrzędnych siatkówki będzie wyglądać na zamazaną, nawet dla normalnych warstw CAL.
- (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]; }
źródło
Powinieneś zrobić 2 rzeczy, pierwsza została wspomniana powyżej:
Rozszerz CATextLayer i ustaw właściwości nieprzezroczyste i contentScale, aby poprawnie obsługiwały wyświetlanie siatkówki, a następnie renderuj z włączonym wygładzaniem dla tekstu.
+ (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]; }
źródło
Jeśli szukałeś tutaj podobnego problemu dla CATextLayer w OSX, po wielu uderzeniach w głowę, otrzymałem ostry, wyraźny tekst, wykonując:
text_layer.contentsScale = self.window!.backingScaleFactor
(Ustawiłem również zawartość warstwy tła widoków Skala tak, aby była taka sama).
źródło
Jest to szybsze i łatwiejsze: wystarczy ustawić skalę treści
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];
źródło