Objective c 按顺序使用图像阵列的动画
我有一个图像数组,我想通过依次播放这些图像来设置动画。我想把整个循环重复几次。我正在为iPad开发一款游戏。向我建议一种方法,在Objective-C中使用Cocoa框架实现此功能。请参阅的Objective c 按顺序使用图像阵列的动画,objective-c,cocoa-touch,ios,animation,Objective C,Cocoa Touch,Ios,Animation,我有一个图像数组,我想通过依次播放这些图像来设置动画。我想把整个循环重复几次。我正在为iPad开发一款游戏。向我建议一种方法,在Objective-C中使用Cocoa框架实现此功能。请参阅的animationImages属性。很难说它是否符合您的需求,因为您没有提供详细信息,但这是一个良好的开端 NSArray *animationArray = [NSArray arrayWithObjects: [UIImage imageNamed:@"
animationImages
属性。很难说它是否符合您的需求,因为您没有提供详细信息,但这是一个良好的开端
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];
在数组中添加您自己的图像。重复计数0表示无限循环。您也可以给出您自己的数字。通过
UIImageView
至少有3种方法可以设置图像数组的动画。我添加了3个链接来下载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];
-cakeyKeyMeanimation这种动画方式通过
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
}
}
-CADisplayLinkCADisplayLink对象是一个计时器对象,允许应用程序将其图形与显示器的刷新率同步。
这样做真的很有趣,并且打开了很多可能性来操纵我们在屏幕上显示的内容
DisplayLink获取程序:
- (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++;
}
一般问题:
尽管我们有3种可能性,如果你的动画有很多大的图像,考虑使用视频代替。内存的使用将大大减少
执行此操作时,您将面临的一个普遍问题是在分配图像时
如果使用[UIImage imageName:@“imageName”],您将遇到cahe问题
来自苹果:
此方法在系统缓存中查找具有指定名称的图像对象,并返回该对象(如果存在)。如果匹配的图像对象不在缓存中,此方法将从磁盘或资产目录中查找并加载图像数据,然后返回结果对象。您不能假定此方法是线程安全的。
因此,imageNamed:
将图像存储在私有缓存中。-第一个问题是您无法控制缓存大小。
-第二个问题是缓存没有及时清理,如果您使用
imagename:
分配大量图像,您的应用程序可能会崩溃
解决方案:
直接从包分配图像
:
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.xcsets
中的图像从未分配。因此,请将您的图像移动到images.xcsets
外部,以便直接从捆绑包进行分配。我的最佳解决方案是使用CADisplayLink。UIImageView没有完成块,您无法捕捉动画的步骤。在我的任务中,我必须用图像序列器一步一步地改变背景视图。因此,CADisplayLink允许您处理步骤和完成动画。若我们讨论内存的使用,我认为最好的解决方案是从bundle加载图像,并在完成后删除数组
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
typedef void(^Block)(void);
@协议图像序列;
@接口QSImageSequencer:UIImageView
@属性(非原子,弱)id委托;
-(void)使用CompletionBlock(块)块启动初始化;
@结束
@协议ImageSequencerDelegate
@可选的
-(void)animationDidStart;
-(void)animationDidStop;
-(void)didChangeImage:(UIImage*)图像;
@结束
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
-(instancetype)初始化{
if(self=[super init]){
_imagesArray=[NSMutableArray];
self.image=[self.imagesArray firstObject];
}
回归自我;
}
#pragma标记-动画
-(无效)启动{
[带完成块的自启动映像:无];
}
-(无效)使用完成块启动初始化:(块)块{
self.frameNumber=0;
[自设置成功块:块];
self.displayLink.frameInterval=5;
if(self.delegate&&[self.delegate respondsToSelector:@selector(animationDidStart)]){
[self.delegate animationDidStart];
}
[self.displayLink addToRunLoop:[NSRunLoop main runloop]
forMode:nsrunlopCommonModes];
}
-(无效)停止设置动画{
self.image=[self.imagesArray lastObject];
[self.displayLink失效];
[自我设置显示链接:无];
Block_uu=[self successBlock];
如果(块){
块_u3;();
}
if(self.delegate&&[self.delegate respondsToSelector:@selector(animationDidStop)]){
[self.delegate animationDidStop];
}
[self.imagesArray removeAllObjects];
}
-(无效)动画进度{
if(self.frameNumber>=self.imagesArray.count){
[自动停止动画];
返回;
}
if(self.delegate&&[self.delegate respondsToSelector:@selector(didChangeImage:)])){
[self.delegate didChangeImage:self.imagesArray[self.frameNumber]];
}
self.image=self.imagesArray[self.frameNumber];
self.frameNumber++;
}
#pragma标记-getter/setter
-(CADisplayLink*)显示链接{
如果(!\u显示链接){
_displayLink=[CADisplayLink displayLinkWithTarget:自选择器:@selector(animationProgress)];
}
返回显示链接;
}
-(NSMutableArray*)图像阵列{
中频成像仪
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)
}
})
}
}
-(void)move
{
[UIView animateWithDuration:5
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
[_imgbox setFrame:CGRectMake(100, 100, _imgbox.frame.size.width, _imgbox.frame.size.height)];
}
completion:^(BOOL finished){
NSLog(@"Done!");
}];
}