0

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"];

私の最初の質問は、アニメーションの開始位置に関係なく、ビューの中心に向かって成長させるにはどうすればよいかということです。ユーザーがコレクション ビュー セルをクリックしているため、現在、ビューの中心に向かって成長するのではなく、そのセルの中心から成長しています。

2 番目の質問は、これから表示する次の画面でフェードをクロスする方法です。次のようなことができると思いました: iPhone で Core Animationを使用して 2 つの画像間をクロスフェードしてクロス フェードを取得する方法ですが、現在まだ表示されていないビューのスクリーンショットを撮る方法がわかりません。

何かご意見は?このアプローチが間違っている場合は、お知らせください。ありがとう。

4

2 に答える 2

1

これが私が取り組んだ別の方法です。スナップショットは使用しませんが、代わりに PageViewController の実際のビューをスケーリングし、containerView の coverView の下にサブビューとして追加してから、同様のアニメーションを実行します。これが「優れたコーディング プラクティス」の観点から優れているかどうかはわかりませんが、別の方法を示しているだけです (私はこのことを独学しているので、別の方法を試しています)。

@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];
    }];
}
于 2012-12-22T00:28:01.947 に答える
0

これは、iBooks のカバーを開くアニメーションを再現する試みです。かなり良さそうです。ViewController は、同じサイズの UIView (pageView) 内にイメージ ビュー (imageView) を持つ最初のコントローラーです。私の例では 90 x 122 です。imageView には本の表紙の画像があり、他のコントローラーのビュー (FirstPageController) のスナップショットの imageView の下にサブビューを追加します。これらのスナップショットの作成について質問があり、あなたも投稿しているのを見ました。ハックのように見える方法で解決しました-FirstPageControllerのビューをビューのサブビューとして追加し、スナップショットを作成してから、ビューから削除しました。うまくいけば、誰かがこれを行うためのより良い方法を提供します。NSLayoutConstraints を使用してサイズ変更とセンタリングを行いました。他のプロジェクトで使用するカテゴリを使用して、そのコードを分離しておきます。

#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 ビューを取得します。

于 2012-12-21T06:53:39.970 に答える