iphone - Antialiasing bordes de UIView después de la transformación utilizando la transformación de CALayer
objective-c rotation (4)
Compruebe la propiedad CALayer
de CALayer
.
block.layer.allowsEdgeAntialiasing = YES; // iOS7 and above.
Tengo un objeto UIView
que gira usando la transformación de CALayer
:
// 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 rotar los bordes del objeto no son antialiasing. Necesito antialias de ellos. Ayudame por favor. ¿Cómo puede hacerse esto?
Simplemente agregue este par clave-valor a su Info.plist : UIViewEdgeAntialiasing
establecido en YES
.
Tuve un problema similar cuando giraba alrededor del eje z. La configuración shouldRasterize = YES evitó los bordes irregulares, sin embargo, tuvo un costo de rendimiento. En mi caso, estaba reutilizando las vistas (y sus capas) y manteniendo que shouldRasterize = YES ralentizaba las cosas.
La solución era apagar la rasterización justo después de que ya no la necesitaba. Sin embargo, como 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 transacción CAT extremadamente útil. Este es un código real que utilicé y debería 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"];
Trabajó 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 no asociada a la vista), sin embargo, espero que funcione siempre que se llame al método CATransaction antes del cambio de propiedad. como garantía, el bloqueo se otorga a CATransaction antes de que comience una animación.
Una forma de hacerlo es colocar la imagen dentro de otra vista que es 5 píxeles más grande. La vista más grande debe tener un borde rasterizado transparente que suavizará los bordes de 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 principal y céntrelo (con 2.5 píxeles alrededor de cada borde).
Finalmente, gire la vista principal en lugar de la vista de imagen.
Funciona muy bien: también puede resumir todo en clase que crea la jerarquía.