2013-04-15 28 views
2

标题可能不是很清楚,但我想要做的是让UIImageView显示一系列图像(有点像gif),我通过将animationImages设置为一组图像,然后调用[imageView startAnimating]; 。这工作正常。我也有用CABasicAnimation来移动UIImageView的代码,而且这个动画代码也能正常工作。但是,当我尝试同时为UIImageView的图像制作动画并尝试移动UIImageView时,UIImageView的图像停止动画。有没有解决方法?如何同时动画UIImageView的图像和UIImageView本身?

这里是我的动画中的UIImageView的内容代码:

self.playerSprite = [[UIImageView alloc] initWithImage:[self.player.animationImages objectAtIndex:0]]; 
    [self.playerSprite setFrame:CGRectMake(self.center.x, self.center.y, self.tileSet.constants.TILE_WIDTH, self.tileSet.constants.TILE_HEIGHT)]; 
    self.playerSprite.animationImages = self.player.animationImages; 
    self.playerSprite.animationDuration = self.tileSet.constants.animationDuration; 
    self.playerSprite.animationRepeatCount = 0; //Makes it repeat indefinitely 

下面是我用一个CABasicAnimation动画的UIImageView的编码:

float playerSpriteX = self.playerSprite.center.x; 
float playerSpriteY = self.playerSprite.center.y; 

CABasicAnimation *moveAnimation = [CABasicAnimation animation]; 
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(playerSpriteX + TILE_WIDTH, playerSpriteY)]; 
[moveAnimation setDelegate:self]; 
[moveAnimation setFillMode:kCAFillModeForwards]; 
[moveAnimation setRemovedOnCompletion:NO]; 
[moveAnimation setDuration:MOVE_ANIMATION_DURATION];  
[self.playerSprite.layer addAnimation:moveAnimation forKey:@"position"]; 

所以GIF效果不工作时UIImageView的位置正在动画化。我的问题是我该如何做到这一点,所以当UIImageView的位置被动画化时,UIImageView会循环显示一组图像。

+0

添加了一些细节和说明视频到我的答案。 – matt

回答

5

这是炒作,我没有测试过这种想法可言,但你有没有考虑实现在同一图像动画时尚你在动画的位置,与CAKeyframeAnimation?你需要构建CGImage对象的数组从UIImage阵列(设置关键帧动画的values财产),但它看起来像一个非常简单的转换:

CAKeyframeAnimation *imageAnimation = [CAKeyframeAnimation animation]; 
imageAnimation.calculationMode = kCAAnimationDiscrete; // or maybe kCAAnimationPaced 
imageAnimation.duration = self.tileSet.constants.animationDuration; 
imageAnimation.repeatCount = HUGE_VALF; 
// the following method will need to be implemented to cast your UIImage array to CGImages 
imageAnimation.values = [self animationCGImagesArray]; 
[self.playerSprite.layer addAnimation:imageAnimation forKey:@"contents"]; 

-(NSArray*)animationCGImagesArray { 
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self.player.animationImages count]]; 
    for (UIImage *image in self.player.animationImages) { 
     [array addObject:(id)[image CGImage]]; 
    } 
    return [NSArray arrayWithArray:array]; 
} 
+0

如何将一个CGImage对象数组存储在一个数组中?我只是把它们投给'(id)'? – pasawaya

+0

是的。你可以通过'[myImage CGImage]'从'UIImage'获得'CGImage'。 –

+0

我非常同意这种方法,我完全重写了我自己的答案! – matt

1

我刚刚做了类似的事情。我使用的代码如下所示:

CGRect r = ziv.frame; 
    r.origin.x += WrongDistance; 
    [ziv startAnimating]; 
    [UIView animateWithDuration:3.0 animations:^(void){ 
     [ziv setFrame:r]; 
    } completion:^(BOOL finished){ 

     [ziv stopAnimating]; 

     if (finished){ 
      // not canceled in flight 
      if (NumWrong == MaxWrong) 
       [self endOfGame:NO]; 
      else 
       [self nextRound:self]; 
     } 
    }]; 

也许您遇到的问题是因为两个动画都在同一个线程上?

1

这不是制作精灵的好方法。我可以坚持认为你应该使用OpenGL,但可能没有必要去那么远;你可以用一个图层的核心动画来完成所有的工作,我想你会比尝试使用完整的UIImageView更好。

使用图层的Core Animation,我可以在打开和闭合嘴巴的同时使这个PacMan sprite在屏幕上生成动画;这不是你想到的那种东西吗?

enter image description here

下面是该动画的视频!

http://www.youtube.com/watch?v=WXCLc9ww8MI

然而实际的代码创建动画是非常简单的:只有两个层动画(核心动画),一个用于改变图像,另一个用于位置。

您应该不是奖励此答案奖励!我现在只是回应西莫斯坎贝尔说的话;我只是填写他的答案的细节。

好了,所以这里的生成上面链接电影代码:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // construct arr, an array of CGImage (omitted) 
    // it happens I've got 5 images, the last being the same as the first 
    self.images = [arr copy]; 
    // place sprite into the interface 
    self.sprite = [CALayer new]; 
    self.sprite.frame = CGRectMake(30,30,24,24); 
    self.sprite.contentsScale = [UIScreen mainScreen].scale; 
    [self.view.layer addSublayer:self.sprite]; 
    self.sprite.contents = self.images[0]; 
} 

- (void)animate { 
    CAKeyframeAnimation* anim = 
     [CAKeyframeAnimation animationWithKeyPath:@"contents"]; 
    anim.values = self.images; 
    anim.keyTimes = @[@0,@0.25,@0.5,@0.75,@1]; 
    anim.calculationMode = kCAAnimationDiscrete; 
    anim.duration = 1.5; 
    anim.repeatCount = HUGE_VALF; 

    CABasicAnimation* anim2 = 
     [CABasicAnimation animationWithKeyPath:@"position"]; 
    anim2.duration = 10; 
    anim2.toValue = [NSValue valueWithCGPoint: CGPointMake(350,30)]; 

    CAAnimationGroup* group = [CAAnimationGroup animation]; 
    group.animations = @[anim, anim2]; 
    group.duration = 10; 

    [self.sprite addAnimation:group forKey:nil]; 
} 
+0

对不起,我不接受。我试图按照链接(最初看起来很有希望),但我做不到。我会尝试你的新代码。谢谢! – pasawaya

+0

只是一个问题:什么是CALayer的“索引”属性? – pasawaya

+0

这就像我指出的教程中的'sampleIndex'属性。基本上,随着'index'的变化,CALayer子类将通过重新绘制序列中的下一幅图像来进行响应。 – matt

1

你的“基本”问题,在此开始行:

CABasicAnimation *moveAnimation = [CABasicAnimation animation]; 

CABasicAnimation对象uses only a single keyframe。这意味着您正在动画的图层的内容会被绘制一次,然后该图像将用于动画的持续时间。

使用CAKeyframeAnimation作为Seamus的建议是一种解决问题的方法 - 关键帧动画将多次重绘动画层的内容,因此为每个关键帧绘制连续的图像将动画化内容以及位置。