开机动画开门效果实现中遇到的隐式动画问题
来源:互联网 发布:微课制作软件免费 编辑:程序博客网 时间:2024/04/27 01:57
毫无疑问,要用layer来做,定义两个layer,一个是leftLayer, 一个是rightLayer,内容分别是开机图片的左半边和右半边,然后设置其围绕y轴旋转的transform了,再然后就是设置动画时间,代码如下所示
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0/2500.0;
[UIView animateWithDuration:3.0 animations:^{
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
transform.m34 = 1.0/2500.0;
[leftLayer removeAllAnimations];
[rightLayer removeAllAnimations];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
{
UIImage *image = [imageView imageOfView];
leftLayer = [CALayer layer];
leftLayer.anchorPoint = CGPointMake(0, 0.5);
leftLayer.frame = CGRectMake(0, 0, 512, 748);
leftLayer.contentsGravity = kCAGravityLeft;
leftLayer.masksToBounds = YES;
leftLayer.contents = (id)[image CGImage];
[self.layer addSublayer:leftLayer];
rightLayer = [CALayer layer];
rightLayer.anchorPoint = CGPointMake(1.0, 0.5);
rightLayer.frame = CGRectMake(512, 0, 512, 748);
rightLayer.contentsGravity = kCAGravityRight;
rightLayer.masksToBounds = YES;
rightLayer.contents = (id)[image CGImage];
[self.layer addSublayer:rightLayer];
[imageView removeFromSuperview];
}
- (void)startAnimation
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0/2500.0;
[leftLayer removeAllAnimations];
[rightLayer removeAllAnimations];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
[CATransaction commit];
double delayInSeconds = 0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[animationView startAnimation];
#import <QuartzCore/QuartzCore.h>
@interface AnimationView : UIView
- (void)prepareStartAnimation;
- (void)startAnimation;
@interface UIView (extented)
- (UIImage *)imageOfView;
@end
@implementation UIView (extented)
- (UIImage *)imageOfView
{
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
@interface AnimationView ()
{
__weak IBOutlet UIImageView *imageView;
CALayer *leftLayer;
CALayer *rightLayer;
}
@end
@implementation AnimationView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)prepareStartAnimation
{
UIImage *image = [imageView imageOfView];
leftLayer = [CALayer layer];
leftLayer.anchorPoint = CGPointMake(0, 0.5);
leftLayer.frame = CGRectMake(0, 0, 512, 748);
leftLayer.contentsGravity = kCAGravityLeft;
leftLayer.masksToBounds = YES;
leftLayer.contents = (id)[image CGImage];
[self.layer addSublayer:leftLayer];
rightLayer = [CALayer layer];
rightLayer.anchorPoint = CGPointMake(1.0, 0.5);
rightLayer.frame = CGRectMake(512, 0, 512, 748);
rightLayer.contentsGravity = kCAGravityRight;
rightLayer.masksToBounds = YES;
rightLayer.contents = (id)[image CGImage];
[self.layer addSublayer:rightLayer];
[imageView removeFromSuperview];
}
- (void)startAnimation
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0/2500.0;
[leftLayer removeAllAnimations];
[rightLayer removeAllAnimations];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
[CATransaction commit];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
{
[super viewDidLoad];
// Do any additional setup after loading the view.
AnimationView *animationView = [[[NSBundle mainBundle] loadNibNamed:@"AnimationView" owner:self options:nil] lastObject];
[self.view addSubview:animationView];
[animationView prepareStartAnimation];
double delayInSeconds = 0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[animationView startAnimation];
});
double delayInSeconds1 = 6.5;
dispatch_time_t popTime1 = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds1 * NSEC_PER_SEC));
dispatch_after(popTime1, dispatch_get_main_queue(), ^(void){
[animationView removeFromSuperview];
});
transform.m34 = 1.0/2500.0;
[UIView animateWithDuration:3.0 animations:^{
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
}];
本人一直比较习惯用UIView自带的动画,但是这样设置后发现,无论动画时间设置多少,运行起来都是固定的,很快。经过网上搜索资料才发现,原来CALayer有些隐藏动画,比如,位置,透明度和颜色改变的时候,它都有自己的隐式动画,所以自己设置的动画就和隐式动画冲突,看到这,一般的思路就是把隐式动画这个属性设置为NO,我也是这么想,在CALayer里面找了半天,试了很多都不是,最后在网上看到关闭隐式动画的语句,如下:
[CATransaction setDisableActions:YES];
在上面的UIView动画前面加上这句话就可以把隐式动画给取消掉。但是问题又来了,无论怎么设置时间,都没有动画了,都是瞬间完成,我了个去。又经过大量查证和实践,解决方法代码如下:
CATransform3D transform = CATransform3DIdentity;transform.m34 = 1.0/2500.0;
[leftLayer removeAllAnimations];
[rightLayer removeAllAnimations];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
[CATransaction commit];
其中,[leftLayer removeAllAnimations];[rightLayer removeAllAnimations];两句话要不要都是可以的。
可能是因为隐式动画的类型就是CATransaction类型的吧,所以你自己设计的动画也要用CATansaction,具体还有没有其他的实现方法,我还真不知道,谁发现了,希望通知我一下。
不要以为这样就完了,正当我以为这样就把所有问题解决了的时候,又遇到一个比较蛋疼的问题,是关于线程的。如下,在实现开机动画的开门效果的时候,我最主要写了两个方法,如下:
- (void)prepareStartAnimation{
UIImage *image = [imageView imageOfView];
leftLayer = [CALayer layer];
leftLayer.anchorPoint = CGPointMake(0, 0.5);
leftLayer.frame = CGRectMake(0, 0, 512, 748);
leftLayer.contentsGravity = kCAGravityLeft;
leftLayer.masksToBounds = YES;
leftLayer.contents = (id)[image CGImage];
[self.layer addSublayer:leftLayer];
rightLayer = [CALayer layer];
rightLayer.anchorPoint = CGPointMake(1.0, 0.5);
rightLayer.frame = CGRectMake(512, 0, 512, 748);
rightLayer.contentsGravity = kCAGravityRight;
rightLayer.masksToBounds = YES;
rightLayer.contents = (id)[image CGImage];
[self.layer addSublayer:rightLayer];
[imageView removeFromSuperview];
}
- (void)startAnimation
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0/2500.0;
[leftLayer removeAllAnimations];
[rightLayer removeAllAnimations];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
[CATransaction commit];
}
第一个方法是准备工作,将imageView保存成图片,然后分别填充到左右两个layer中,第二个方法就是动画开始的方法了,调用的时候先调用第一个方法,然后再调用第一个方法,这时候问题出现了,如果两个方法连着调用,如下:
[animationView prepareStartAnimation]; [animationView startAnimation];
动画效果就没有了,但是如果调用第一个方法后延迟一下,即使延迟一点点时间,运行都是正常的,代码如下:
[animationView prepareStartAnimation];double delayInSeconds = 0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[animationView startAnimation];
});
如上所示,延迟时间设置为0都可以,但是将两个方法连着调用就是不行。如果有大神知道为什么欢迎一起讨论。下面将此效果实现代码奉上:
AnimationView.h
#import <UIKit/UIKit.h>#import <QuartzCore/QuartzCore.h>
@interface AnimationView : UIView
- (void)prepareStartAnimation;
- (void)startAnimation;
@end
AnimationView.m
#import "AnimationView.h"@interface UIView (extented)
- (UIImage *)imageOfView;
@end
@implementation UIView (extented)
- (UIImage *)imageOfView
{
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
@interface AnimationView ()
{
__weak IBOutlet UIImageView *imageView;
CALayer *leftLayer;
CALayer *rightLayer;
}
@end
@implementation AnimationView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)prepareStartAnimation
{
UIImage *image = [imageView imageOfView];
leftLayer = [CALayer layer];
leftLayer.anchorPoint = CGPointMake(0, 0.5);
leftLayer.frame = CGRectMake(0, 0, 512, 748);
leftLayer.contentsGravity = kCAGravityLeft;
leftLayer.masksToBounds = YES;
leftLayer.contents = (id)[image CGImage];
[self.layer addSublayer:leftLayer];
rightLayer = [CALayer layer];
rightLayer.anchorPoint = CGPointMake(1.0, 0.5);
rightLayer.frame = CGRectMake(512, 0, 512, 748);
rightLayer.contentsGravity = kCAGravityRight;
rightLayer.masksToBounds = YES;
rightLayer.contents = (id)[image CGImage];
[self.layer addSublayer:rightLayer];
[imageView removeFromSuperview];
}
- (void)startAnimation
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0/2500.0;
[leftLayer removeAllAnimations];
[rightLayer removeAllAnimations];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
leftLayer.transform = CATransform3DRotate(transform, -M_PI/2, 0, 1, 0);
rightLayer.transform = CATransform3DRotate(transform, M_PI/2, 0, 1, 0);
[CATransaction commit];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
该类的xib文件中就一个imageView。以下是调用的代码:
MainViewController.m
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view.
AnimationView *animationView = [[[NSBundle mainBundle] loadNibNamed:@"AnimationView" owner:self options:nil] lastObject];
[self.view addSubview:animationView];
[animationView prepareStartAnimation];
double delayInSeconds = 0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[animationView startAnimation];
});
double delayInSeconds1 = 6.5;
dispatch_time_t popTime1 = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds1 * NSEC_PER_SEC));
dispatch_after(popTime1, dispatch_get_main_queue(), ^(void){
[animationView removeFromSuperview];
});
}
- 开机动画开门效果实现中遇到的隐式动画问题
- 43_实现开门动画效果
- android开门动画效果
- 微信开门动画的实现
- android 动画实现中遇到的问题及源码
- 学习COCOS2D-x 精灵动画 实现一个《热血传奇》开门效果
- QT中实现开机动画
- ios 动画CoreAnimation中遇到的问题
- 开门动画
- 动画效果的实现
- Android中动画效果的实现(转)
- Android中动画效果的实现
- HTML5中动画实现的效果
- 关于开机动画的问题
- css 开门-透视perspective动画效果
- 类似开门的动画-iOS
- 开机动画 渐渐变大的效果
- ios动画中抖动动画效果的实现与CALayer动画的基本理解
- 一些数据库优化方面的经验
- APP免费时代需注意什么
- SQLSERVER高效分页查询
- NSMutableAttributedString IOS中的富文本
- 如何JAVA编程
- 开机动画开门效果实现中遇到的隐式动画问题
- 解压assets资源文件夹的压缩文件,并下载到SD卡中。
- 指针偏移
- 2013这一年,我都干嘛了
- HTTP中Get与Post的区别
- 分页语句
- jshint 安装使用
- SQL SERVER 2005如何建立自动备份的维护计划
- leetcode: Two Sum