首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用UIImageView动画制作流畅的动画

用UIImageView动画制作流畅的动画
EN

Stack Overflow用户
提问于 2014-01-19 03:03:45
回答 2查看 2.2K关注 0票数 4

我目前正在4幅图片之间动画,如下所示:

代码语言:javascript
复制
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];

它工作得很好,只是动画在图像之间是起伏不定的。我需要的持续时间正好是.75秒,所以加快速度不是一种选择。

怎样才能使动画在图像之间更加流畅,就像每一次图像变化之间的混合一样?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-19 04:21:07

如果您使用的是基于框架的UIImageView动画,并且动画必须是.75秒,那么我所知道的使其更加流畅的唯一方法就是创建更多的帧。尝试30帧每秒,或约22帧。这应该会使运动非常顺利。

如果您希望在帧之间进行某种交叉分解,那么您将无法使用UIView帧动画。您必须使用UIView块动画(使用animateWithDuration:animations:或其表亲)。

您可以在您的帧之间创建一个交叉溶解序列,其中序列的总持续时间为.75秒。让每个转换触发它的完成块中的下一个转换。

就像这样:

你将需要两个图像视图,堆叠在一起。你会同时淡出一个,另一个消失。您需要在这两种情况下将不透明标志设置为NO。

让我们称它们为tom3BeforeImage1和tom3BeforeImage2

添加一个int实例变量imageCount,并将图像、tom3Images和实例变量的数组设置为:

代码语言:javascript
复制
- (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];
    }
  ];
}

请注意,我在论坛编辑器中没有喝够咖啡就完成了上面的代码。它可能包含语法错误,甚至可能存在逻辑问题。这只是让你思考如何去做。

编辑2:

我不知道为什么,但我决定把它充实成一个完整的示例项目。上面的代码在调试后工作得很好,但是由于它同时淡出了一个图像,而另一个正在逐渐淡出,所以这两个图像视图背后的背景都会显示出来。

我对它进行了重新设计,使它的逻辑只消去了上面的图像。它将第一帧放置在顶部图像视图中,第二帧放置在底部图像视图中,然后淡出顶部图像视图。

该项目位于github上,名为动画-Img。(链接)

然后将第三帧安装在最上面的图像视图中,然后将其淡入,

然后在底部图像视图中安装第四声名,然后淡出顶部以暴露底部等。

最后,我创建了一个通用的方法

代码语言:javascript
复制
- (void) animateImagesWithDuration: (CGFloat) totalDuration
                           reverse: (BOOL) reverse
                         crossfade: (BOOL) doCrossfade
               withCompletionBlock: (void (^)(void)) completionBlock;

它会将一组图像动画化,变成一对图像视图,在动画完成后,还可以选择倒置动画。它需要一个完成块,该块一旦动画完成就会被调用。

动画按钮实际上调用了一个重复整个动画序列的方法。它目前只被设置为只运行一次,但是如果需要的话,更改常量将使程序重复整个序列。

票数 5
EN

Stack Overflow用户

发布于 2015-07-31 12:06:41

我确实需要有动画阵列的图像。最初,当我使用图像视图的animationImages属性时,我得到了所需的动画,但是图像之间的转换并不顺利,然后我使用CAKeyframeAnimation来实现平滑过渡,捕获是使用timingFunction和正确的calculationMode。我不确定这是问题的确切答案,但这是使动画更流畅的一种方法,下面是这个问题的代码

有关计算模式的更多信息,请参见苹果文档

代码语言:javascript
复制
- (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"];
}

更新- Swift 3

代码语言:javascript
复制
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")
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21212708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档