8

iOS プロジェクトで人気の「折り紙/折り紙」効果を実装する方法に関するヒントを探しています。

https://github.com/xyfeng/XYOrigamiなどのプロジェクトを認識してい ます が、「アニメーション化」効果のみを提供し、オープニング アニメーションを手動で制御することはできません。

私はそのプロジェクトを分析し、私が求めているものを思いつくのに苦労しました.

より正確には、ここに示されている効果を実装する方法を探しています: http://vimeo.com/41495357折り畳みアニメーションが単に開いているのではなく、ユーザーが折り畳みを開くのを制御します。

どんな助けでも大歓迎です、事前に感謝します!

編集:

さて、私が苦労していることをよりよく説明するためのコード例を次に示します。

このメソッドは、折り紙効果のアニメーションをトリガーします。

- (void)showOrigamiTransitionWith:(UIView *)view 
                NumberOfFolds:(NSInteger)folds 
                     Duration:(CGFloat)duration
                    Direction:(XYOrigamiDirection)direction
                   completion:(void (^)(BOOL finished))completion
{

if (XY_Origami_Current_State != XYOrigamiTransitionStateIdle) {
    return;
}
XY_Origami_Current_State = XYOrigamiTransitionStateUpdate;

//add view as parent subview
if (![view superview]) {
    [[self superview] insertSubview:view belowSubview:self];
}


//set frame
CGRect selfFrame = self.frame;
CGPoint anchorPoint;
if (direction == XYOrigamiDirectionFromRight) {

    selfFrame.origin.x = self.frame.origin.x - view.bounds.size.width;

    view.frame = CGRectMake(self.frame.origin.x+self.frame.size.width-view.frame.size.width, self.frame.origin.y, view.frame.size.width, view.frame.size.height);

    anchorPoint = CGPointMake(1, 0.5);
}
else {
    selfFrame.origin.x = self.frame.origin.x + view.bounds.size.width;
    view.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, view.frame.size.width, view.frame.size.height);

    anchorPoint = CGPointMake(0, 0.5);
}

UIGraphicsBeginImageContext(view.frame.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewSnapShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//set 3D depth
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0/800.0;
CALayer *origamiLayer = [CALayer layer];
origamiLayer.frame = view.bounds;
origamiLayer.backgroundColor = [UIColor colorWithWhite:0.2 alpha:1].CGColor;
origamiLayer.sublayerTransform = transform;
[view.layer addSublayer:origamiLayer];






//setup rotation angle
double startAngle;
CGFloat frameWidth = view.bounds.size.width;
CGFloat frameHeight = view.bounds.size.height;
CGFloat foldWidth = frameWidth/(folds*2);
CALayer *prevLayer = origamiLayer;
for (int b=0; b < folds*2; b++) {
    CGRect imageFrame;
    if (direction == XYOrigamiDirectionFromRight) {
        if(b == 0)
            startAngle = -M_PI_2;
        else {
            if (b%2)
                startAngle = M_PI;
            else
                startAngle = -M_PI;
        }
        imageFrame = CGRectMake(frameWidth-(b+1)*foldWidth, 0, foldWidth, frameHeight);
    }
    else {
        if(b == 0)
            startAngle = M_PI_2;
        else {
            if (b%2)
                startAngle = -M_PI;
            else
                startAngle = M_PI;
        }
        imageFrame = CGRectMake(b*foldWidth, 0, foldWidth, frameHeight);
    }
    CATransformLayer *transLayer = [self transformLayerFromImage:viewSnapShot Frame:imageFrame Duration:duration AnchorPiont:anchorPoint StartAngle:startAngle EndAngle:0];
    [prevLayer addSublayer:transLayer];
    prevLayer = transLayer;
}

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    self.frame = selfFrame;
    [origamiLayer removeFromSuperlayer];
    XY_Origami_Current_State = XYOrigamiTransitionStateShow;

    if (completion)
        completion(YES);
}];

[CATransaction setValue:[NSNumber numberWithFloat:duration] forKey:kCATransactionAnimationDuration];
CAAnimation *openAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position.x" function:openFunction fromValue:self.frame.origin.x+self.frame.size.width/2 toValue:selfFrame.origin.x+self.frame.size.width/2];
openAnimation.fillMode = kCAFillModeForwards;
[openAnimation setRemovedOnCompletion:NO];
[self.layer addAnimation:openAnimation forKey:@"position"];
[CATransaction commit];
}

メソッドは、このメソッドから CATransform レイヤーを取得します。

- (CATransformLayer *)transformLayerFromImage:(UIImage *)image Frame:(CGRect)frame Duration:(CGFloat)duration AnchorPiont:(CGPoint)anchorPoint StartAngle:(double)start EndAngle:(double)end;
{
CATransformLayer *jointLayer = [CATransformLayer layer];
jointLayer.anchorPoint = anchorPoint;
CGFloat layerWidth;
if (anchorPoint.x == 0) //from left to right
{
    layerWidth = image.size.width - frame.origin.x;
    jointLayer.frame = CGRectMake(0, 0, layerWidth, frame.size.height);
    if (frame.origin.x) {
        jointLayer.position = CGPointMake(frame.size.width, frame.size.height/2);
    }
    else {
        jointLayer.position = CGPointMake(0, frame.size.height/2);
    }
}
else 
{ //from right to left
    layerWidth = frame.origin.x + frame.size.width;
    jointLayer.frame = CGRectMake(0, 0, layerWidth, frame.size.height);
    jointLayer.position = CGPointMake(layerWidth, frame.size.height/2);
}

//map image onto transform layer
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
imageLayer.anchorPoint = anchorPoint;
imageLayer.position = CGPointMake(layerWidth*anchorPoint.x, frame.size.height/2);
[jointLayer addSublayer:imageLayer];
CGImageRef imageCrop = CGImageCreateWithImageInRect(image.CGImage, frame);
imageLayer.contents = (__bridge id)imageCrop;
imageLayer.backgroundColor = [UIColor clearColor].CGColor;

//add shadow
NSInteger index = frame.origin.x/frame.size.width;
double shadowAniOpacity;
CAGradientLayer *shadowLayer = [CAGradientLayer layer];
shadowLayer.frame = imageLayer.bounds;
shadowLayer.backgroundColor = [UIColor darkGrayColor].CGColor;
shadowLayer.opacity = 0.0;
shadowLayer.colors = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor, (id)[UIColor clearColor].CGColor, nil];
if (index%2) {
    shadowLayer.startPoint = CGPointMake(0, 0.5);
    shadowLayer.endPoint = CGPointMake(1, 0.5);
    shadowAniOpacity = (anchorPoint.x)?0.24:0.32;
}
else {
    shadowLayer.startPoint = CGPointMake(1, 0.5);
    shadowLayer.endPoint = CGPointMake(0, 0.5);
    shadowAniOpacity = (anchorPoint.x)?0.32:0.24;
}
[imageLayer addSublayer:shadowLayer];


//animate open/close animation
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
[animation setDuration:duration];
[animation setFromValue:[NSNumber numberWithDouble:start]];
[animation setToValue:[NSNumber numberWithDouble:end]];
[animation setRemovedOnCompletion:NO];
[jointLayer addAnimation:animation forKey:@"jointAnimation"];



//animate shadow opacity
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
[animation setDuration:duration];
[animation setFromValue:[NSNumber numberWithDouble:(start)?shadowAniOpacity:0]];
[animation setToValue:[NSNumber numberWithDouble:(start)?0:shadowAniOpacity]];
[animation setRemovedOnCompletion:NO];
[shadowLayer addAnimation:animation forKey:nil];

return jointLayer;
}

基本的に、自動アニメーションを削除し、手動で設定した値 (uislider 値やコンテンツ オフセットなど) を使用してエフェクトの進行を制御する必要があります。

繰り返しますが、提供されたヘルプは大歓迎です!

4

3 に答える 3

8

I write another library for folding transition : https://github.com/geraldhuard/YFoldView

Hope it works for you.

于 2012-06-27T16:12:57.997 に答える
6

これを試して。用紙の折り目を左右にドラッグして制御できます。

https://github.com/honcheng/PaperFold-for-iOS

于 2012-08-18T17:11:58.563 に答える
2

これは私が見た中で最高の解決策です:

http://api.mutado.com/mobile/paperstack/

編集:これはどうですか:iPadのtwitterでの紙の折りたたみ/展開効果

于 2012-06-22T14:12:42.100 に答える