Сглаживание краев UIView после преобразования с использованием преобразования CALayer
У меня есть объект 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);
После поворота края объекта не сглаживаются. Мне нужно сгладить их.
Помоги мне, пожалуйста. Как это можно сделать?
Ответы
Ответ 1
Один из способов сделать это - поместить изображение в другое представление, которое на 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 пикселями вокруг каждого края).
Наконец, поверните родительский вид вместо представления изображения.
Это работает очень хорошо - вы можете также инкапсулировать все это в классе, который создает иерархию.
Ответ 2
Просто добавьте эту пару ключ-значение в свой Info.plist: UIViewEdgeAntialiasing
установите на YES
.
Ответ 3
Проверить allowsEdgeAntialiasing
свойство CALayer
.
block.layer.allowsEdgeAntialiasing = YES; // iOS7 and above.
Ответ 4
У меня была аналогичная проблема при вращении вокруг оси z. Установка shouldRasterize = YES предотвращала появление зубчатых кромок, однако она достигала стоимости исполнения. В моем случае я повторно использовал представления (и его слои) и сохранял ifRasterize = 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 до начала анимации.