Подтвердить что ты не робот

Сглаживание краев 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);

После поворота края объекта не сглаживаются. Мне нужно сгладить их. Помоги мне, пожалуйста. Как это можно сделать?

4b9b3361

Ответ 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 до начала анимации.