使用CALayer变换进行变换后,对UIView的边缘进行抗锯齿处理

时间:2011-11-29 15:59:45

标签: iphone objective-c uiview rotation antialiasing

我有一个UIView对象,可以使用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);

旋转对象的边缘后不进行抗锯齿处理。我需要反他们。 请帮帮我。怎么办呢?

4 个答案:

答案 0 :(得分:43)

执行此操作的一种方法是将图像放在另一个大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像素)。

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

它非常有效 - 您还可以将整个事物封装在创建层次结构的类中。

答案 1 :(得分:37)

只需将此键值对添加到 Info.plist UIViewEdgeAntialiasing设置为YES

答案 2 :(得分:25)

检查allowsEdgeAntialiasing的{​​{1}}属性。

CALayer

答案 3 :(得分: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。