我目前正在制作4张这样的图像:
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 :(得分:4)
如果您正在使用基于帧的UIImageView动画,并且动画必须是.75秒,那么我知道的唯一方法是使其更流畅是创建更多帧。尝试30帧/秒,或约22帧。这应该是非常平稳的动作。
如果你想在帧之间进行某种交叉溶解,那么你将无法使用UIView帧动画。你将不得不使用UIView块动画(使用animateWithDuration:animations:
或其表兄弟。)
您可以在帧之间创建一系列交叉溶解,其中序列的总持续时间为.75秒。让每个转换触发其完成块中的下一个转换。
这样的事情:
您需要两个图像视图,彼此叠加。你会同时淡出一个,另一个淡入淡出。您需要在两者上将opaque标志设置为NO。
让我们称之为tom3BeforeImage1和tom3BeforeImage2
添加一个int实例变量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];
}
];
}
请注意,在没有足够咖啡的情况下,我在论坛编辑器中删除了上面的代码。它可能包含语法错误,甚至可能存在逻辑问题。这只是为了让你思考如何做到这一点。
编辑#2:
我不知道为什么,但我决定将其充实为一个成熟的示例项目。上面的代码在调试后可以很好地工作,但是由于它同时淡化了一个图像,它正在淡化另一个图像,两个图像视图背后的背景显示出来。
我将其重新设计为具有仅消除顶部图像的逻辑。它将第一帧放在顶部图像视图中,将第二帧放在底部图像视图中,然后淡出顶部图像视图。
该项目在github上发布,名为Animate-Img。 (链接)
然后它在顶部图像视图中安装第三帧并将其淡入IN,
然后它在底部图像视图中安装第4个成名并淡出顶部以暴露底部等等。
我最终创建了一个通用方法
- (void) animateImagesWithDuration: (CGFloat) totalDuration
reverse: (BOOL) reverse
crossfade: (BOOL) doCrossfade
withCompletionBlock: (void (^)(void)) completionBlock;
它会将一组图像动画化为一对图像视图,可选择在动画完成后将其反转。它需要一个动画完成后调用的完成块。
动画按钮实际上调用重复整个动画序列的方法。它目前设置为仅运行一次,但是如果需要,更改常量将使程序重复整个序列。
答案 1 :(得分:3)
我确实要求拥有包含图像数组的动画。最初,当我使用imageview的animationImages
属性时,我得到了所需的动画,但是图像之间的过渡并不平滑,然后我使用CAKeyframeAnimation
来实现平滑过渡,捕获是使用{{1与正确的timingFunction
一起。我不确定这是问题的答案,但这是使动画更流畅的一种方法,
下面是那个
有关计算模式的详细信息,请参阅Apple Documentation
calculationMode
UPDATE- Swift 3
- (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"];
}