Удалить интерполяцию свойства содержимого CALayer - PullRequest
2 голосов
/ 02 декабря 2010

Повторное задание вопроса:

Когда вы добавляете анимацию для ключа содержимого, очевидно, запускается CATransitionAnimation, которая переводит исходное свойство содержимого в первое значение в массиве значений анимации, что приводит к25 секунд исчезают.И это выглядит плохо!Я подавил каждое свойство анимации, используя все методы, обсуждаемые здесь (возврат нулевой анимации через делегата в словарь действий, используя CATransaction), но ни одна из них, похоже, не предназначена для этой конкретной анимации перехода.

alt text

Я изучал, какое свойство может за это отвечать, но не могу понять.

Мне нужно подавить анимацию перехода, которая происходит, когда вы добавляете анимацию кключ содержимого.

Поскольку я в такой растерянности, я добавлю анимацию ключевого кадра, которая будет добавлена ​​для вас.Я полагаю, что я здесь что-то не так делаю?Просто обратите внимание, что массив - это просто массив из 6 CGImageRef (кадров анимации).

+ (CAKeyframeAnimation *)moveLeftAnimation {

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
animation.values = [NSArray arrayWithArray:[Setzer walkingLeftSprite]];
animation.duration = 0.5f;
animation.keyTimes = [NSArray arrayWithObjects:
                      [NSNumber numberWithFloat:0.0], 
                      [NSNumber numberWithFloat:0.2], 
                      [NSNumber numberWithFloat:0.4],
                      [NSNumber numberWithFloat:0.6],
                      [NSNumber numberWithFloat:0.8],
                      [NSNumber numberWithFloat:1.0],
                      nil];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
return animation;

}

Кроме того, у меня есть анимация, которая обрабатывает клавишу положения, всловарь действий спрайта:

+ (CABasicAnimation *)moveAnimation {

CABasicAnimation *moveAnimation = [CABasicAnimation animation];
moveAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
moveAnimation.duration = 0.5f;

return moveAnimation;

}

Я думаю, может быть, этот переход происходит, когда вы меняете положение слоя?Я не знаю ...

Пожалуйста, помогите!Это сводит меня с ума!

Ответы [ 3 ]

1 голос
/ 06 декабря 2010

Вы можете сделать что-то в соответствии с тем, что я описал в этом ответе , где я отключаю неявную анимацию для различных свойств слоя, устанавливая соответствующие значения в словаре actions на этом слое.

В вашем случае, я полагаю, что-то вроде

NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                   [NSNull null], @"contents",
                                   nil];
layer.actions = newActions;
[newActions release];

должно предотвращать неявную анимацию свойства contents слоя, пока вы не явно его анимируете.

1 голос
/ 09 декабря 2010

Вот несколько заметок о том, как эта головоломка была решена, и о том, как ответы каждого из них послужили частью головоломки.

Чтобы еще раз сформулировать проблему: когда я добавил анимацию ключевого кадра к ключу @contents CALayer, между исходным свойством содержимого и первым кадром анимации ключевого кадра произошел переход в 25 секунд. Это выглядело плохо, и я хотел избавиться от этого.

Сначала я наверняка подумал, что, используя CATransaction, я смогу подавить эту неявную анимацию перехода, так как именно это заставляет вас верить документам Apple. Используя транзакцию, я подавлял все возможные способы, которые вы могли себе представить, и все же это все еще происходило. Затем я попытался вернуть NULL-анимацию для каждого анимируемого свойства через словарь. Неудачно. Затем я сделал то же самое, но с делегатом. Все еще не повезло.

Что я не упомянул, так это то, что в то же время добавлялась анимация и слой перемещался, два подслоя под ним удалялись из их суперслоев. Я попытался добавить пользовательские анимации для клавиши onOrderOut, но безрезультатно. Затем я наткнулся на еще один вопрос здесь, в StackOverflow, о добавлении пользовательской анимации для ключа onOrderOut. Проще говоря, это невозможно, и если вы хотите реализовать какую-то другую анимацию для удаления подслоя, вы должны использовать метод delagate animationDidStop. Как я могу использовать пользовательские анимации для onOrderOut в Core Animation?

Так что в этот момент я был убежден, что это изображение-призрак не имеет никакого отношения к реальному слою, о котором идет речь, к самому спрайту. Чтобы проверить это, я просто не добавил подслои, которые шли под ним. Конечно же, когда я переместил спрайт, не было никакого затянувшегося призрака. Выглядело идеально. Затем я добавил слои под призраком. Это было почти так, как будто содержимое спрайта было нарисовано в слоях под ним, так что, когда они были удалены, был какой-то отпечаток.

Вместо удаления подслоев я просто пытался их скрыть. Бинго. Это было идеально. Произошел такой же переход замирания, но не осталось отпечатка спрайта. Я до сих пор не понимаю, почему это так.

Затем, поскольку мне все еще нужно было удалить эти слои, я реализовал метод делегата animationDidStop для различных анимаций движения спрайта, чтобы удалить их.

Это оригинал:

alt text

Это новая версия:

alt text

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

Так что спасибо всем за помощь. Я знаю, что это странный вариант использования, но если вы когда-нибудь задумывались о том, чтобы сделать 2-граммовый финал Final Fantasy Tactics на основе спрайтов, то, надеюсь, моя боль будет вам полезна!

1 голос
/ 02 декабря 2010

Чтобы предотвратить любую анимацию, вы можете установить объект в качестве делегата вашего CALayer, а затем реализовать метод делегата ‑actionForLayer:forKey: и вернуть нулевой объект:

- (id<CAAction>)actionForLayer:(CALayer*)layer forKey:(NSString*)key 
{
    if(layer == yourLayer)
    {
        if([key isEqualToString:@"contents"])
        {
            return (id<CAAction>)[NSNull null];
        }
    }
    return nil;
}
...