2011-11-29 145 views
22

我有一个旋转使用CALayer的变换UIView对象:抗锯齿边缘改造后

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

旋转物体的边缘后不抗锯齿。我需要对他们进行抗锯齿。 请帮助我。如何做呢?

回答

41

这样做的一种方法是将图像放在另一个5像素大的视图中。更大的看法应该有一个透明光栅化边界,将平滑的UIImageView的边缘:

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

然后,把你的UIImageView这个父视图内居中(拥有约每边2.5像素)。

最后,旋转父视图而不是图像视图。

它工作得很好 - 你也可以在创建层次结构的类中封装整个事情。

+9

您可能需要添加'view.layer.rasterizationScale = [[UIScreen mainScreen] scale];'以避免在Retina屏幕上模糊。 –

+0

此评论应该是答案的一部分。设置'shouldRasterize'属性是不够的! –

+0

你说得对。完成。 – tarmes

30

只需将此键值对添加到您的Info.plistUIViewEdgeAntialiasing设置为YES

+1

这是杀手! – orkenstein

+0

太棒了!对性能有何影响? – horseshoe7

+0

它带有性能损失,如果可以的话就避免它。 –

3

我在围绕z轴旋转时遇到了类似的问题。设置shouldRasterize = YES可以防止锯齿状的边缘,但是会降低性能。在我的情况下,我重新使用视图(及其图层)并保持shouldRasterize = YES会减慢速度。

解决方法是,在我不需要它之后立即关闭光栅化。然而,由于动画运行在另一个线程上,所以无法知道动画何时完成......直到我发现一个非常有用的CATransaction方法。这是我使用的一个实际的代码,它应该说明它的用途:

// 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"]; 

对我来说就像一个魅力。

我还没有尝试过在隐式动画中使用它(例如,由于非视图关联图层的动画属性中的值更改而发生的动画),但是我希望它只要在之前调用CATransaction方法属性发生变化,就像在动画启动之前块被赋予CATransaction一样。

20

支票allowsEdgeAntialiasing财产CALayer

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

就像上面(Info.plist),但更精细的控制!优秀! – horseshoe7

+1

接受的答案的确如此工作,但这一个表现更好。两者都使用相同的RAM,但该解决方案为用户提供更高的FPS。 –

+0

此属性的文档说如果Info.plist值不存在,则值为NO。显然,你不能简单地设置这个属性,但必须与plist一起使用它。如果没有设置属性,我还没有测试过会发生什么,但从AddisDev的答案来看,它在此情况下默认为yes。因此,如果性能受到影响并且您不需要抗锯齿功能,那么似乎要做的就是将此值设置为NO。 –