复制iBooks缩放/淡入淡出动画

时间:2012-12-20 03:45:48

标签: ios core-animation

我试图复制iPad上发生的书籍动画的放大和淡入淡出。基本上如果你还没有看到一本书放在书架上,当被轻拍时它会朝着屏幕的中心生长。当它接近屏幕的中心时,它会与您所在书籍的页面交叉淡化,无论是封面还是页面100.在iPhone上,书的封面朝屏幕中心增长,然后中途通过过渡,它会淡入您在书中所在的最后一页,并且缩放完成占据整个屏幕。

为了复制这个,我尝试做的是,有人点击我的collectionView。我得到该单元格的框架并截取该单元格的屏幕截图。我创建了一个内容为该图像的图层。

CALayer *smallLayer = [CALayer layer];
UIImage *smallImage = [UIImage renderImageFromView:self.smallZoomView];
smallLayer.frame = self.smallZoomRect;
smallLayer.contents = (__bridge id)smallImage.CGImage;

我将它添加到我用于动画的容器视图中。对于动画部分,我尝试了这个:

[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
[CATransaction setDisableActions:YES];

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
anim.fromValue = [NSNumber numberWithFloat:1.0];
anim.toValue = [NSNumber numberWithFloat:2.0];

[self.smallZoomLayer addAnimation:anim forKey:@"Zoom"];

我的第一个问题是,无论动画从何处开始,如何让它朝着视图的中心增长。由于用户点击了一个集合视图单元格,它当前只是从该单元格的中心增长而不是向视图中心增长。

我的第二个问题是如何在我要展示的下一个屏幕上淡入淡出。我想我可以做这样的事情:How to crossfade between 2 images on iPhone using Core Animation以获得交叉渐变,但我不知道如何拍摄当前尚未显示的视图的截图。

有什么想法?如果这种方法有误,请告诉我!感谢。

2 个答案:

答案 0 :(得分:1)

这是我工作的另一种方式。它不使用快照,而是缩放PageViewController的实际视图,将其添加为coverView下面的子视图,在containerView中,然后执行类似的动画。我不知道从“良好的编码实践”的角度来看这是否更好,但它只是展示了另一种方式(我一直在教自己这些东西,所以我正在尝试不同的选择)。 / p>

@interface ViewController ()
@property (strong,nonatomic) UIView *pageView;
@property (strong,nonatomic) PageController *pageVC;
@end

@implementation ViewController 

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.pageVC = [self.storyboard instantiateViewControllerWithIdentifier:@"Page"]; // controller with the page contnent
    self.pageView = self.pageVC.view;
    self.pageView.transform = CGAffineTransformMakeScale(self.coverView.frame.size.width/self.pageView.frame.size.width, self.coverView.frame.size.height/self.pageView.frame.size.height);
    [self.containerView insertSubview:self.pageView belowSubview:self.coverView];
    [self.containerView constrainViewEqual:self.pageView];
}


-(IBAction)openCover:(id)sender {
    self.coverView.layer.anchorPoint = CGPointMake(0, .5);
    self.coverView.center = CGPointMake(self.coverView.center.x - self.coverView.frame.size.width/2, self.coverView.center.y);

    [self.containerView removeConstraints:self.containerView.constraints];
    [self.view removeConstraints:self.view.constraints];

    [self.view constrainViewEqual:self.containerView];
    [self.containerView constrainViewLeft:self.coverView];
    [self.containerView constrainViewEqual:self.pageView];

    NSInteger animationTime = 1;

    [UIView animateWithDuration:animationTime animations:^{
          self.pageView.transform = CGAffineTransformIdentity;
          [self.view layoutIfNeeded];
     }];
    [UIView animateWithDuration:animationTime animations:^{
        CATransform3D transform = CATransform3DIdentity;
        transform =CATransform3DMakeRotation(M_PI_2, 0.0, -1.0, 0.0);
        transform.m34 = 1/1000.0;
        transform.m14 = -2/10000.0;
        self.coverView.layer.transform =transform;
    } completion:^(BOOL finished) {
        [self.view.window addSubview:self.pageView];
        [self.view.window setRootViewController:self.pageVC];
    }];
}

答案 1 :(得分:0)

这是我尝试重新创建iBooks开放封面动画。我觉得它看起来很不错。 ViewController是初始控制器,在相同大小的UIView(pageView)中有一个图像视图(imageView),在我的例子中是90 x 122。 imageView有一个书籍封面的图像,我在另一个控制器的视图(FirstPageController)的快照的imageView下添加一个子视图 - 我有一个关于制作这些快照的问题,我看到你也发布了一个。我通过看起来像是一个黑客来解决它 - 我添加了FirstPageController的视图作为我的视图的子视图,做了快照,然后从我的视图中删除它。希望有人能提供更好的方法来实现这一目标。我使用NSLayoutConstraints进行了一些大小调整和居中,我在其他项目中使用了一个类别来保持代码分离。这是ViewController.m代码:

#import "ViewController.h"
#import "UIView+RDConstraintsAdditions.h"
#import <QuartzCore/QuartzCore.h>
#import "FirstPageController.h"

@interface ViewController ()
@property (strong,nonatomic) FirstPageController *fpController;
@end

@implementation ViewController


- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.fpController = [self.storyboard instantiateViewControllerWithIdentifier:@"FirstPage"];

    [self.view insertSubview:self.fpController.view belowSubview:self.view];

    UIGraphicsBeginImageContext(self.fpController.view.bounds.size);
    [self.fpController.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self.fpController.view removeFromSuperview];

    self.imageView2 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 90, 122)];
    self.imageView2.image = viewImage;
    [self.pageView insertSubview:self.imageView2 belowSubview:self.imageView];
}


-(IBAction)expandImageView:(id)sender {
    self.imageView.layer.anchorPoint = CGPointMake(0, .5);
    self.imageView.center = CGPointMake(self.imageView.center.x - self.imageView.frame.size.width/2, self.imageView.center.y);
    [self.view removeConstraints:self.view.constraints];
    [self.pageView removeConstraints:self.pageView.constraints];
    [self.view constrainViewEqual:self.pageView];
    [self.pageView constrainViewLeft:self.imageView];
    [self.pageView constrainViewEqual:self.imageView2];
    [UIView animateWithDuration:2 animations:^{
        [self.view layoutIfNeeded];
    }];
    [UIView animateWithDuration:2 animations:^{
        CATransform3D transform = CATransform3DIdentity;
        transform =CATransform3DMakeRotation(M_PI_2, 0.0, -1.0, 0.0);
        transform.m34 = 1/1000.0;
        transform.m14 = -2/10000.0;
        self.imageView.layer.transform =transform;
    } completion:^(BOOL finished) {
        [self.view.window setRootViewController:self.fpController];
    }];
}

以下是我使用的UIView类别:

#import "UIView+RDConstraintsAdditions.h"

@implementation UIView (RDConstraintsAdditions)

-(void)constrainViewEqual:(UIView *) view {
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
    NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
    NSLayoutConstraint *con2 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    NSLayoutConstraint *con3 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:0 toItem:view attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
    NSLayoutConstraint *con4 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:0 toItem:view attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
    NSArray *constraints = @[con1,con2,con3,con4];
    [self addConstraints:constraints];
}

-(void)constrainViewLeft:(UIView *) view {
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
    NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:0 toItem:view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
    NSLayoutConstraint *con2 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    NSLayoutConstraint *con3 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:0 toItem:view attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
    NSLayoutConstraint *con4 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:0 toItem:view attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
    NSArray *constraints = @[con1,con2,con3,con4];
    [self addConstraints:constraints];
}

在动画结束时,我切换窗口的根视图控制器以获取“实时”FirstPageController视图而不是快照。