我目前正在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];它工作得很好,只是动画在图像之间是起伏不定的。我需要的持续时间正好是.75秒,所以加快速度不是一种选择。
怎样才能使动画在图像之间更加流畅,就像每一次图像变化之间的混合一样?
谢谢!
发布于 2014-01-19 04:21:07
如果您使用的是基于框架的UIImageView动画,并且动画必须是.75秒,那么我所知道的使其更加流畅的唯一方法就是创建更多的帧。尝试30帧每秒,或约22帧。这应该会使运动非常顺利。
如果您希望在帧之间进行某种交叉分解,那么您将无法使用UIView帧动画。您必须使用UIView块动画(使用animateWithDuration:animations:或其表亲)。
您可以在您的帧之间创建一个交叉溶解序列,其中序列的总持续时间为.75秒。让每个转换触发它的完成块中的下一个转换。
就像这样:
你将需要两个图像视图,堆叠在一起。你会同时淡出一个,另一个消失。您需要在这两种情况下将不透明标志设置为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上,名为动画-Img。(链接)
然后将第三帧安装在最上面的图像视图中,然后将其淡入,
然后在底部图像视图中安装第四声名,然后淡出顶部以暴露底部等。
最后,我创建了一个通用的方法
- (void) animateImagesWithDuration: (CGFloat) totalDuration
reverse: (BOOL) reverse
crossfade: (BOOL) doCrossfade
withCompletionBlock: (void (^)(void)) completionBlock;它会将一组图像动画化,变成一对图像视图,在动画完成后,还可以选择倒置动画。它需要一个完成块,该块一旦动画完成就会被调用。
动画按钮实际上调用了一个重复整个动画序列的方法。它目前只被设置为只运行一次,但是如果需要的话,更改常量将使程序重复整个序列。
发布于 2015-07-31 12:06:41
我确实需要有动画阵列的图像。最初,当我使用图像视图的animationImages属性时,我得到了所需的动画,但是图像之间的转换并不顺利,然后我使用CAKeyframeAnimation来实现平滑过渡,捕获是使用timingFunction和正确的calculationMode。我不确定这是问题的确切答案,但这是使动画更流畅的一种方法,下面是这个问题的代码
有关计算模式的更多信息,请参见苹果文档。
- (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
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")
}https://stackoverflow.com/questions/21212708
复制相似问题