2011-11-29 12 views
22

I tienen un objeto UIView que gira usando CALayer 's de transformación:bordes de suavizado de líneas de UIView después de la transformación utilizando CALayer de transformada

// Create uiview object. 
UIImageView *block = [[UIImageView alloc] initWithFrame....] 

// Apply rotation. 
CATransform3D basicTrans = CATransform3DIdentity; 
basicTrans.m34 = 1.0/-distance; 
blockImage.layer.transform = CATransform3DRotate(basicTrans, rangle, 1.0f, 0.0f, 0.0f); 

Después de la rotación de los bordes del objeto no son antialiasing. Necesito antialias. Ayúdame, por favor. ¿Cómo puede hacerse esto?

Respuesta

41

Una forma de hacerlo es colocando la imagen dentro de otra vista que sea 5 píxeles más grande. La vista más grande debería tener un borde de datos de trama transparente que suavizar los bordes de la UIImageView:

view.layer.borderWidth = 3; 
view.layer.borderColor = [UIColor clearColor].CGColor; 
view.layer.shouldRasterize = YES; 
view.layer.rasterizationScale = [[UIScreen mainScreen] scale]; 

Luego, coloque su UIImageView dentro de esta vista padre y centrarla (Con 2,5 píxeles alrededor de cada borde).

Finalmente, gire la vista principal en lugar de la vista de la imagen.

Funciona muy bien: también puede encapsular todo en clase que crea la jerarquía.

+9

Es posible que desee añadir 'view.layer.rasterizationScale = [[UIScreen mainScreen] escala];' para evitar borrosa en las pantallas Retina. –

+0

Este comentario debería ser parte de la respuesta. Establecer la propiedad 'shouldRasterize' no es suficiente! –

+0

Tienes razón. Hecho. – tarmes

30

Simplemente agregue este par clave-valor a su Info.plist: UIViewEdgeAntialiasing establecido en YES.

+1

¡Esto es asesino! – orkenstein

+0

¡fantástico! ¿Alguna idea del golpe de rendimiento? – horseshoe7

+0

Viene con una penalización de rendimiento, evítelo si puede. –

3

Tuve un problema similar al girar alrededor del eje z. El ajuste shouldRasterize = YES evitó los bordes irregulares, sin embargo, tuvo un costo de rendimiento. En mi caso, estaba reutilizando los puntos de vista (y sus capas) y manteniendo el orden shouldRasterize = YES estaba ralentizando las cosas.

La solución fue apagar la rasterización inmediatamente después de que ya no la necesité. Sin embargo, dado que la animación se ejecuta en otro hilo, no había forma de saber cuándo se completó la animación ... hasta que descubrí un método de CATransaction extremadamente útil. Este es un código real que utilicé y debe ilustrar su uso:

// Create a key frame animation 
CAKeyframeAnimation *wiggle = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 
NSInteger frequency = 5; // Higher value for faster vibration 
NSInteger amplitude = 25; // Higher value for lower amplitude 
// Create the values it will pass through  
NSMutableArray *valuesArray = [[NSMutableArray alloc] init]; 
NSInteger direction = 1; 

[valuesArray addObject:@0.0]; 

for (NSInteger i = frequency; i > 0; i--, direction *= -1) { 
    [valuesArray addObject:@((direction * M_PI_4 * (CGFloat)i/(CGFloat)amplitude))]; 
} 

[valuesArray addObject:@0.0]; 
[wiggle setValues:valuesArray]; 

// Set the duration 
[wiggle setAdditive:YES]; 
[wiggle setValueFunction:[CAValueFunction functionWithName:kCAValueFunctionRotateZ]]; 
[wiggle setDuration:0.6]; 

// Turn on rasterization to prevent jagged edges (anti-aliasing issues) 
viewToRotate.layer.shouldRasterize = YES; 

// ************ Important step ************** 
// Very usefull method. Block returns after ALL animations have completed. 
[CATransaction setCompletionBlock:^{ 
    viewToRotate.layer.shouldRasterize = NO; 
}]; 
// Animate the layer 
[viewToRotate.layer addAnimation:wiggle forKey:@"wiggleAnimation"]; 

funcionó como un encanto para mí.

No he intentado usar esto con animaciones implícitas (es decir, animaciones que ocurren debido al cambio de valor en la propiedad animable para una capa asociada no visible), sin embargo, esperaría que funcionara siempre que se llame al método CATransaction el cambio de propiedad, solo como una garantía, el bloque se le da a CATransaction antes de que comience una animación.

20

marca allowsEdgeAntialiasing propiedad de CALayer.

block.layer.allowsEdgeAntialiasing = YES; // iOS7 and above. 
+1

al igual que arriba (Info.plist) pero control más granular! ¡Excelente! – horseshoe7

+1

La respuesta aceptada funciona igual que esta, pero esta funciona mejor. Ambos gastan la misma RAM, pero esta solución ofrece mayor FPS para el usuario. –

+0

La documentación de esta propiedad indica que el valor es NO si el valor Info.plist está ausente.Aparentemente, no puedes simplemente establecer solo esta propiedad, sino que debes usarla junto con la lista. No he probado lo que sucede si la propiedad no está configurada, pero a juzgar por la respuesta de AddisDev, en ese caso se establece "sí". Entonces, si hay un golpe de rendimiento y no necesita un antialiasing, parece que lo que hay que hacer es establecer este valor en NO. –

Cuestiones relacionadas