【问题标题】:Replicating iBooks zoom/fade animation复制 iBooks 缩放/淡入淡出动画
【发布时间】:2012-12-20 03:45:47
【问题描述】:

我正在尝试复制 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 让交叉淡入淡出,但我不知道如何截取当前尚未显示的视图的屏幕截图。

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

【问题讨论】:

  • 嗯....这对我来说看起来不像是交叉淡入淡出。看起来这本书移动到中心并随着封面打开而展开以显示一个空白的白色页面,该页面快速切换到实际的页面视图(我假设它是在加载新的视图控制器时)。
  • @rdelmar 很有趣。关于如何完成的任何想法?谢谢!

标签: ios core-animation


【解决方案1】:

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

@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];
    }];
}

【讨论】:

    【解决方案2】:

    这是我重新创建 iBooks 打开封面动画的尝试。我觉得它看起来很不错。 ViewController 是初始控制器,它在相同大小的 UIView (pageView) 内具有图像视图 (imageView),在我的示例中为 90 x 122。 imageView 有一个书籍封面的图像,我在另一个控制器视图(FirstPageController)的快照的 imageView 下添加了一个子视图——我对制作这些快照有疑问,我看到你也发布了一个。我通过看似 hack 的方式解决了它——我将 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 视图而不是快照。

    【讨论】:

    • 但这让我很困惑,所以如果你给我一个完整的项目,那么它对我有很大帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-01-20
    • 2012-12-18
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    相关资源
    最近更新 更多