Анимация с использованием массива изображений в последовательности

У меня есть массив изображений, которые я хочу оживить, играя эти изображения один за другим в последовательности. Я хочу повторить весь цикл несколько раз. Я разрабатываю игру для iPad. Предложите мне метод достижения этой функциональности в Objective-C с каркасом Cocoa.

5 Solutions collect form web for “Анимация с использованием массива изображений в последовательности”

См. Свойство animationImages UIImageView . Трудно сказать, соответствует ли это вашим потребностям, поскольку вы не даете нам подробностей, но это хорошее начало.

 NSArray *animationArray = [NSArray arrayWithObjects: [UIImage imageNamed:@"images.jpg"], [UIImage imageNamed:@"images1.jpg"], [UIImage imageNamed:@"images5.jpg"], [UIImage imageNamed:@"index3.jpg"], nil]; UIImageView *animationView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0,320, 460)]; animationView.backgroundColor = [UIColor purpleColor]; animationView.animationImages = animationArray; animationView.animationDuration = 1.5; animationView.animationRepeatCount = 0; [animationView startAnimating]; [self.view addSubview:animationView]; [animationView release]; 

добавьте свои собственные изображения в массив.repeat Count 0 означает бесконечный цикл. Вы также можете указать свой собственный номер.

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

Первый – это тот, который все знают. Другие менее известны.

– UIImageView.animationImages
Пример ссылки

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

Точно так же нет возможности автоматически сохранить последнее изображение из анимации в UIImageView . Если мы объединим обе проблемы, у нас может быть пробел в конце анимации, если мы хотим сохранить последний кадр на экране.

 self.imageView.animationImages = self.imagesArray; // the array with the images self.imageView.animationDuration = kAnimationDuration; // static const with your value self.imageView.animationRepeatCount = 1; [self.imageView startAnimating]; 

– CAKeyframeAnimation
Пример ссылки

Этот способ анимации работает через CAAnimation . У него есть удобный делегат для использования, и мы можем знать, когда закончится анимация.

Вероятно, это лучший способ анимации массива изображений.

 - (void)animateImages { CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; keyframeAnimation.values = self.imagesArray; keyframeAnimation.repeatCount = 1.0f; keyframeAnimation.duration = kAnimationDuration; // static const with your value keyframeAnimation.delegate = self; // keyframeAnimation.removedOnCompletion = YES; keyframeAnimation.removedOnCompletion = NO; keyframeAnimation.fillMode = kCAFillModeForwards; CALayer *layer = self.animationImageView.layer; [layer addAnimation:keyframeAnimation forKey:@"girlAnimation"]; } 

Делегат:

 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { if (flag) { // your code } } 

– CADisplayLink
Пример ссылки

A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display.

Этот способ сделать это действительно интересен и открывает множество возможностей манипулировать тем, что мы показываем на экране.

Отображаемый getLink:

 - (CADisplayLink *)displayLink { if (!_displayLink) { _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(linkProgress)]; } return _displayLink; } 

Методы:

 - (void)animateImages { self.displayLink.frameInterval = 5; self.frameNumber = 0; [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } - (void)linkProgress { if (self.frameNumber > 16) { [self.displayLink invalidate]; self.displayLink = nil; self.animationImageView.image = [UIImage imageNamed:@"lastImageName"]; self.imagesArray = nil; return; } self.animationImageView.image = self.imagesArray[self.frameNumber++]; self.frameNumber++; } 

ОБЩАЯ ПРОБЛЕМА:

Несмотря на то, что у нас есть три возможности, если ваша анимация имеет много больших изображений, подумайте об использовании видео. Использование памяти значительно уменьшится.

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

Если вы используете [UIImage imageNamed: @ "imageName"], у вас возникнут проблемы.

От Apple:

This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method locates and loads the image data from disk or asset catelog, and then returns the resulting object. You can not assume that this method is thread safe.

Итак, imageNamed: сохраняет изображение в приватном кэше.
– Первая проблема заключается в том, что вы не можете контролировать размер кеша.
– Вторая проблема заключается в том, что кеш не очищался вовремя, и если вы выделяете много изображений с помощью imageNamed: ваше приложение, вероятно, выйдет из imageNamed: .

РЕШЕНИЕ:

Выделите изображения непосредственно из Bundle :

 NSString *imageName = [NSString stringWithFormat:@"imageName.png"]; NSString *path = [[NSBundle mainBundle] pathForResource:imageName // Allocating images with imageWithContentsOfFile makes images to do not cache. UIImage *image = [UIImage imageWithContentsOfFile:path]; 

Небольшая проблема:

Изображения в Images.xcassets никогда не выделяются. Таким образом, перемещайте изображения вне Images.xcassets чтобы выделить их прямо из Bundle.

Лучшее решение для меня использует CADisplayLink. UIImageView не имеет блока завершения, и вы не можете поймать шаги анимации. В моей задаче я должен постепенно менять фон представления с помощью секвенсора изображений. Таким образом CADisplayLink позволяет обрабатывать шаги и завершать анимацию. Если мы говорим об использовании памяти, я думаю, что лучшее решение загружает изображения из набора и удаления массива после завершения

ImageSequencer.h

 typedef void (^Block)(void); @protocol ImageSequencerDelegate; @interface QSImageSequencer : UIImageView @property (nonatomic, weak) id <ImageSequencerDelegate> delegate; - (void)startAnimatingWithCompletionBlock:(Block)block; @end @protocol ImageSequencerDelegate <NSObject> @optional - (void)animationDidStart; - (void)animationDidStop; - (void)didChangeImage:(UIImage *)image; @end 

ImageSequencer.m

 - (instancetype)init { if (self = [super init]) { _imagesArray = [NSMutableArray array]; self.image = [self.imagesArray firstObject]; } return self; } #pragma mark - Animation - (void)startAnimating { [self startAnimatingWithCompletionBlock:nil]; } - (void)startAnimatingWithCompletionBlock:(Block)block { self.frameNumber = 0; [self setSuccessBlock:block]; self.displayLink.frameInterval = 5; if (self.delegate && [self.delegate respondsToSelector:@selector(animationDidStart)]) { [self.delegate animationDidStart]; } [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } -(void)stopAnimating { self.image = [self.imagesArray lastObject]; [self.displayLink invalidate]; [self setDisplayLink:nil]; Block block_ = [self successBlock]; if (block_) { block_(); } if (self.delegate && [self.delegate respondsToSelector:@selector(animationDidStop)]) { [self.delegate animationDidStop]; } [self.imagesArray removeAllObjects]; } - (void)animationProgress { if (self.frameNumber >= self.imagesArray.count) { [self stopAnimating]; return; } if (self.delegate && [self.delegate respondsToSelector:@selector(didChangeImage:)]) { [self.delegate didChangeImage:self.imagesArray[self.frameNumber]]; } self.image = self.imagesArray[self.frameNumber]; self.frameNumber++; } #pragma mark - Getters / Setters - (CADisplayLink *)displayLink { if (!_displayLink){ _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animationProgress)]; } return _displayLink; } - (NSMutableArray<UIImage *> *)imagesArray { if (_imagesArray.count == 0) { // get images from bundle and set to array } return _imagesArray; } @end 

Я добавил расширение версии 3.0 для этого

 extension UIImageView { func animate(images: [UIImage], index: Int = 0, completionHandler: (() -> Void)?) { UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: { self.image = images[index] }, completion: { value in let idx = index == images.count-1 ? 0 : index+1 if idx == 0 { completionHandler!() } else { self.animate(images: images, index: idx, completionHandler: completionHandler) } }) } } 
  • Могу ли я получить номер телефона пользователя, запросив разрешение в ios 6?
  • Различать центр уведомлений, скрывающийся и возвращающийся с фона с уведомлением DidBecomeActive
  • Программно / вручную создать MKPlacemark / CLPlacemark
  • Разница между и
  • Анимация пользовательского свойства подкласса CAShapeLayer на основе свойства path
  • Как отключить сенсорный ввод ко всем представлениям, кроме самого верхнего вида?
  • Emoji и UIWebView в iOS 5
  • Paypal с кнопкой корзины покупок в iphone
  • Как потерять margin / padding в UITextView?
  • Символы, не найденные для архитектуры i386 - Но работает для устройства iOS
  • iOS: Есть ли способ открыть защищенные паролем документы Microsoft Office?
  • PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.