2014-01-19 3 views
4

Я в настоящее время анимации между 4 изображений, как это:Создать плавную анимацию с UIImageView анимации

UIImageView *tom3BeforeImage; 
tom3Images = [NSArray arrayWithObjects: [UIImage imageNamed:@"floortom_before1.png"],[UIImage imageNamed:@"floortom_before2.png"],[UIImage imageNamed:@"floortom_before3.png"],[UIImage imageNamed:@"floortom_before4.png"], nil ]; 
tom3BeforeImage.animationImages = tom3Images; 
tom3BeforeImage.animationDuration = 0.75; 
[tom3BeforeImage startAnimating]; 

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

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

Спасибо!

+0

в качестве альтернативы можно изменить изображение вручную, е. изменение свойства .image. Вы можете использовать таймер для изменения свойства изображения. – iCoder

ответ

4

Если вы используете анимацию UIImageView на основе рамок, а анимация должна быть 0,75 секунды, тогда единственный способ, которым я знаю, сделать ее более гладкой, - создать больше кадров. Попробуйте 30 кадров в секунду или около 22 кадров. Это должно дать очень плавное движение.

Если вы хотите какое-то перекрестное растворение между кадрами, вы не сможете использовать анимацию кадра UIView. вам нужно будет использовать анимацию блока UIView (используя или ее двоюродных братьев.)

Вы можете создать последовательность перекрестных растворов между вашими кадрами, где общая длительность последовательности составляет .75 секунд. Каждый переход запускает следующий переход в своем блоке завершения.

Что-то вроде этого:

Вам нужно 2 просмотры изображения, сложенные друг на друга. В то же время вы будете исчезать и друг друга. Вам нужно установить для непрозрачного флага значение НЕТ на обоих.

Назовём их tom3BeforeImage1 и tom3BeforeImage2

Добавить переменную imageCount ИНТ экземпляра и сделать свой массив изображений, tom3Images, и переменная экземпляра, а также:

- (void) animateImages; 
{ 
    CGFloat duration = .75/([tom3Images count] -1); 

    //Start with the current image fully visible in tom3BeforeImage1 
    tom3BeforeImage1.image = tom3Images[imageCount]; 
    tom3BeforeImage1.alpha = 1.0; 

    //Get the next image ready, at alpha 0, in tom3BeforeImage2 
    tom3BeforeImage2.image = tom3Images[imageCount+1]; 
    tom3BeforeImage2.alpha = 0; 
    imageCount++ 

    [UIView animateWithDuration: duration 
    delay: 0 
    options: UIViewAnimationOptionCurveLinear 
    animations: 
    ^{ 
     //Fade out the current image 
     tom3BeforeImage1.alpha = 0.0; 

     //Fade in the new image 
     tom3BeforeImage2.alpha = 1.0; 
    } 
    completion: 
    ^{ 
    //When the current animation step completes, trigger the method again. 
    if (imageCount < [tom3Images count] -1) 
     [self animateImages]; 
    } 
    ]; 
} 

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

Edit # 2:

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

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

Проект находится на github, который называется Animate-Img. (Ссылка)

Затем он устанавливает третий кадр в виде сверху изображения и исчезает его,

Затем он устанавливает 4-ю известность в виде снизу изображения и исчезает через верх, чтобы обнажить дно и т.д., и т.п.

я в конечном итоге создание обобщенного метода

- (void) animateImagesWithDuration: (CGFloat) totalDuration 
          reverse: (BOOL) reverse 
         crossfade: (BOOL) doCrossfade 
       withCompletionBlock: (void (^)(void)) completionBlock; 

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

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

+0

Спасибо Дункан. Можете ли вы привести мне пример или указать мне правильное направление, потому что крест растворяется? – codeman

+0

@codeman, я обновил свой ответ некоторым (непроверенным) кодом. Это потребует отладки. –

+0

@codeman, я добавил пример проекта на github (ссылка в моем оригинальном посте). –

2

У меня было требование иметь анимацию с массивом изображений. Первоначально, когда я использовал свойство imageview, я получил желаемую анимацию, но переход между изображениями не был гладким, я тогда использовал CAKeyframeAnimation для достижения плавного перехода, уловкой является использование timingFunction наряду с правильным calculationMode. Я не уверен, что это точный ответ на вопрос, но это один из способов, чтобы сделать анимацию более гладкой, ниже код для этого

Для получения дополнительной информации о режиме расчета см Apple Documentation

- (void) animate 
{ 
    NSMutableArray * imageArray = [[NSMutableArray alloc] init]; 

    int imageCount = 8; 

    for (int i=0; i<=imageCount; i++) { 
     [imageArray addObject:(id)[UIImage imageNamed:[NSString stringWithFormat:@“image%d”,i]].CGImage]; 
    } 

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; 
    animation.calculationMode = kCAAnimationLinear;// Make sure this is kCAAnimationLinear or kCAAnimationCubic other mode doesnt consider the timing function 
    animation.duration = 8.0; 
    animation.values = imageArray; 
    animation.repeatCount = 1; // Change it for repetition 
    animation.removedOnCompletion = NO; 
    animation.fillMode = kCAFillModeForwards; // To keep the last frame when animation ends 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    [imageView.layer addAnimation:animation forKey:@"animation"]; 
} 

update- Свифта 3

func animate() { 
    var imageArray = [CGImage]() 
    let imageCount: Int = 3 
    for i in 0...imageCount { 
     imageArray.append((UIImage(named: String(format:"image\(i)"))?.cgImage!)!) 
    } 
    let animation = CAKeyframeAnimation(keyPath: "contents") 
    animation.calculationMode = kCAAnimationLinear 
    // Make sure this is kCAAnimationLinear or kCAAnimationCubic other mode doesnt consider the timing function 
    animation.duration = CFTimeInterval(floatLiteral: 8.0) 
    animation.values = imageArray 
    animation.repeatCount = 1 
    // Change it for repetition 
    animation.isRemovedOnCompletion = false 
    animation.fillMode = kCAFillModeForwards 
    // To keep the last frame when animation ends 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
    animImageView.layer.add(animation, forKey: "animation") 
} 
+1

Прекрасно работает. – Kumar

Смежные вопросы