我目前正在 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];
Run Code Online (Sandbox Code Playgroud)
它工作正常,除了图像之间的动画断断续续。我需要的持续时间正好是 0.75 秒,所以加快速度不是一种选择。
让动画在图像之间更平滑的最佳方法是什么,有点像在每个图像变化之间进行混合?
谢谢!
如果您使用基于帧的 UIImageView 动画,并且动画必须为 0.75 秒,那么我所知道的使其更流畅的唯一方法是创建更多帧。尝试 30 帧/秒,或大约 22 帧。那应该给出非常平滑的运动。
如果您想在帧之间进行某种交叉融合,那么您将无法使用 UIView 帧动画。你将不得不使用 UIView 块动画(使用animateWithDuration:animations:或其表亲。)
您可以在帧之间创建一系列交叉溶解,其中该序列的总持续时间为 0.75 秒。让每个转换触发它的完成块中的下一个转换。
像这样的东西:
您需要 2 个图像视图,彼此堆叠在一起。您将同时淡出另一个。您需要在两者上将 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];
}
];
}
Run Code Online (Sandbox Code Playgroud)
请注意,我在没有喝足够咖啡的情况下在论坛编辑器中敲出了上面的代码。它可能包含语法错误,甚至可能有逻辑问题。这只是让你思考如何去做。
编辑#2:
我不知道为什么,但我决定把它充实到一个完整的示例项目中。上面的代码在调试后运行良好,但由于它同时淡出一幅图像,同时淡入另一幅图像,因此两个图像视图背后的背景都显示出来了。
我对其进行了重新设计,使其具有仅淡入淡出顶部图像的逻辑。它将第一帧放在顶部图像视图中,将第二帧放在底部图像视图中,然后淡出顶部图像视图。
该项目位于 github 上,名为Animate-Img。(关联)
然后它在顶部图像视图中安装第三帧并将其淡入,
然后它在底部图像视图中安装第四个成名并淡出顶部以暴露底部等。
我最终创建了一个通用方法
- (void) animateImagesWithDuration: (CGFloat) totalDuration
reverse: (BOOL) reverse
crossfade: (BOOL) doCrossfade
withCompletionBlock: (void (^)(void)) completionBlock;
Run Code Online (Sandbox Code Playgroud)
它会将一组图像动画化为一对图像视图,完成后可以选择反转动画。它需要一个完成块,一旦动画完成就会被调用。
动画按钮实际上调用了一个重复整个动画序列的方法。它当前设置为仅运行一次,但如果需要,更改常量将使程序重复整个序列。
我确实需要有包含图像数组的动画。最初,当我使用animationImagesimageview 的属性时,我得到了所需的动画,但图像之间的过渡不平滑,然后我用它CAKeyframeAnimation来实现平滑过渡,问题是timingFunction与正确的calculationMode. 我不确定这是否是问题的确切答案,但这是使动画更平滑的一种方法,\n 下面是该代码
有关计算模式的更多信息,请参阅Apple 文档
\n\n- (void) animate\n{\n NSMutableArray * imageArray = [[NSMutableArray alloc] init];\n\n int imageCount = 8;\n\n for (int i=0; i<=imageCount; i++) {\n [imageArray addObject:(id)[UIImage imageNamed:[NSString stringWithFormat:@\xe2\x80\x9cimage%d\xe2\x80\x9d,i]].CGImage];\n }\n\n CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];\n animation.calculationMode = kCAAnimationLinear;// Make sure this is kCAAnimationLinear or kCAAnimationCubic other mode doesnt consider the timing function\n animation.duration = 8.0;\n animation.values = imageArray;\n animation.repeatCount = 1; // Change it for repetition\n animation.removedOnCompletion = NO;\n animation.fillMode = kCAFillModeForwards; // To keep the last frame when animation ends\n animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];\n [imageView.layer addAnimation:animation forKey:@"animation"];\n}\nRun Code Online (Sandbox Code Playgroud)\n\n更新 - Swift 3
\n\nfunc animate() {\n var imageArray = [CGImage]()\n let imageCount: Int = 3\n for i in 0...imageCount {\n imageArray.append((UIImage(named: String(format:"image\\(i)"))?.cgImage!)!)\n }\n let animation = CAKeyframeAnimation(keyPath: "contents")\n animation.calculationMode = kCAAnimationLinear\n // Make sure this is kCAAnimationLinear or kCAAnimationCubic other mode doesnt consider the timing function\n animation.duration = CFTimeInterval(floatLiteral: 8.0)\n animation.values = imageArray\n animation.repeatCount = 1\n // Change it for repetition\n animation.isRemovedOnCompletion = false\n animation.fillMode = kCAFillModeForwards\n // To keep the last frame when animation ends\n animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)\n animImageView.layer.add(animation, forKey: "animation")\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2077 次 |
| 最近记录: |