CABasicAnimation не является анимацией.Помогите? - PullRequest
2 голосов
/ 26 июня 2011

Теперь, прежде чем вы начнете беспокоиться, это Какао Я говорю, а не Какао-Touch .С этого, давайте начнем.Я недавно начал программировать для Mac.Зачем?Потому что это круто.Вы знаете, что не круто?Не в состоянии иметь красивые модные анимации, как другие классные дети.Я не могу понять это, и если ты поможешь мне, ты спасешь несколько волосков, которые я оставил на моей голове.

Хорошо, у меня есть NSCollectionView.Мне понадобилось много времени, чтобы понять это, но что угодно.Я сделал это NSCollectionView на основе слоев в Интерфейсном Разработчике.Я слышал, что это должно заставить эту магию работать.Я попытался сделать это, чтобы анимировать мою коллекцию:

//usersView is my NSCollectionView
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];    
CATransform3D scale = CATransform3DMakeScale(2.0, 2.0, 0.0);
[anim setFromValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
[anim setToValue:[NSValue valueWithCATransform3D:scale]];
[anim setDuration:1.0f];
[[usersView layer] addAnimation:anim forKey:nil];
[[usersView layer] setTransform:scale];

А вот и дело: он преобразует вид, но не с классной анимацией.Я также попробовал это:

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
[CATransaction setValue:[NSNumber numberWithFloat:3.0f] forKey:kCATransactionAnimationDuration];
[usersView layer].transform = CATransform3DMakeScale(2.0, 2.0, 0.0);
[CATransaction commit];

Никаких кубиков.Я верю, что мне нужна помощь.Благодарю.

Ответы [ 3 ]

2 голосов
/ 27 июня 2011

Я полагаю, что для вашего второго фрагмента кода, который пытается выполнить неявную анимацию (назначая новое значение для свойства transform), вам необходимо пропустить установку свойства kCATransactionDisableActions на true, так как в действительности это говорит не для оживления перехода (что в точности противоположно вашему намерению).Чтобы быть в явном виде, вы можете установить это свойство на false. Также могут быть и другие проблемы;Кажется, я никогда не знаю точно, что нужно, пока он не закодирован и не запущен.(С основной анимацией я всегда чувствую, что постепенно приближаюсь к результату, который я хочу. Но после получения хотя бы чего-то для анимации, это действительно вдохновляет меня продолжать дорабатывать код, пока он не будет работать так, как я этого хочу!, т.е. ядро ​​анимации не так легко подобрать.)

Что касается первой проблемы, явной анимации, я думаю, что одна проблема связана с последней строкой, где вы устанавливаете преобразование слояимущество;Я бы начал с того, что не учел это (хотя, возможно, в конечном итоге это придется отработать в другом месте).Установка этого преобразования немедленно изменяет слой так, как он должен выглядеть, когда анимация завершена (именно поэтому вы видите, что преобразование происходит немедленно), но это не полностью объясняет отсутствие анимации после транзакции (которая начинается после завершения кода).т. е. после того, как произошел немедленный переход), имеет как начальное, так и конечное значение.Для начала я бы нашел пример кода, который выполняет похожую анимацию, и менял его по частям, чтобы получить то, что вы хотите.(Вот так я научился использовать базовую анимацию после того, как попытался полностью закодировать анимацию самостоятельно и потерпел неудачу; потребовалось много времени, чтобы сделать это правильно, но я действительно почувствовал это лучше.) Вы могли бы такжехочу вернуться к документации и действительно попытаться получить концепцию core animation rendering architecture, то есть дерево-слой, дерево представления и render-дерево и то, что отображается на разных этапах анимации, а также то, как на него воздействовать (которое опять-таки действительно утонет только после множества проб и ошибок).Просто придерживайтесь этого, пока это не имеет смысла!

1 голос
/ 28 апреля 2015

Вы можете использовать

[usersView setWantsLayer:YES];

, если выясните, что ваш слой равен нулю.По умолчанию все виды не имеют слоев.

0 голосов
/ 10 апреля 2016

После нескольких попыток у меня наконец-то заработали анимации.Есть несколько вещей, за которыми нужно следить.

Если вы хотите, чтобы преобразование было закреплено в центре, то вам следует позвонить anchorPoint на CALayer: перед добавлением вид на его суперпредставление!В противном случае подпредставление будет обрезано, начиная с местоположения anchorPoint.

CALayer *layer = _completionIndicator.layer;
layer.anchorPoint = CGPointMake(.5, .5);

Обернуть вызовы анимации в блоке runAnimationGroup (_completionIndicator - это свойство, определенное какNSView и centerInSuperview определены ниже):

[self.contentView addSubview:_completionIndicator];
[_completionIndicator centerInSuperview];

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
    CGFloat duration = <#duration#>;

    CALayer *layer = _completionIndicator.layer;
    CABasicAnimation *animation;

    //Transform
    animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(<#scale#>, <#scale#>, 1.0)];
    animation.toValue =   [NSValue valueWithCATransform3D:CATransform3DIdentity];
    [animation setDuration:duration];
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = NO;
    [layer addAnimation:animation forKey:@"zoomIn"];

    //Fade
    animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.fromValue = [NSNumber numberWithFloat:0.0];
    animation.toValue =   [NSNumber numberWithFloat:1.0];
    [animation setDuration:duration];
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = NO;
    [layer addAnimation:animation forKey:@"fadeIn"];
} completionHandler:^{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        [NSThread sleepForTimeInterval:<#seconds#>];
        dispatch_sync(dispatch_get_main_queue(), ^{
            [self hideCompletionIndicator];
        });

    });

}];

Установка fillMode была необходима для плавной анимации.По умолчанию kCAFillModeRemoved, что вызывает скачки при запуске анимации после первого запуска.

В OSX 10.11 установка wantsLayer в NSView не требуется.Я не знаю о предыдущих версиях.

Чтобы скрыть вид, просто сделайте обратное и удалите вид в блоке завершения:

- (void) hideCompletionIndicator
{
    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
        CGFloat duration = <#duration#>;

        CALayer *layer = _completionIndicator.layer;
        CABasicAnimation *animation;

        //Transform
        animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
        animation.toValue =   [NSValue valueWithCATransform3D:CATransform3DMakeScale(<#scale#>, <#scale#>, 1.0)];
        [animation setDuration:duration];
        animation.fillMode = kCAFillModeForwards;
        animation.removedOnCompletion = NO;
        [layer addAnimation:animation forKey:@"zoomOut"];

        //Fade
        animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        animation.fromValue = [NSNumber numberWithFloat:1.0];
        animation.toValue =   [NSNumber numberWithFloat:0.0];
        [animation setDuration:duration];
        animation.fillMode = kCAFillModeForwards;
        animation.removedOnCompletion = NO;
        [layer addAnimation:animation forKey:@"fadeOut"];
    } completionHandler:^{
        [_completionIndicator removeFromSuperview];
    }];
}

Реализация категории NSView

@implementation NSView (Additions)

- (void) centerInSuperview
{
    [self centerInView:[self superview]];
}

- (void) centerInView:(NSView *)otherView
{
    int w = self.frame.size.width;
    int h = self.frame.size.height;
    int x = (otherView.frame.size.width - w)/2;
    int y = (otherView.frame.size.height - h)/2;

    self.frame = NSMakeRect(x, y, w, h);

}

@end

Интерфейс категории NSView

@interface NSView (Additions)

- (void) centerInSuperview;
- (void) centerInView:(NSView *)otherView;

@end
...