2011-11-29 102 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。 –