iOS纸折(折纸/手风琴)效果动画,带手动控制

8
我正在寻找如何在我的iOS项目中实现流行的“纸折/折纸”效果的技巧。
我已经了解到一些项目,例如: https://github.com/xyfeng/XYOrigami 但是它们只提供了“动画”效果,没有手动控制开启动画的选项。
我努力分析该项目并得出所需功能,但是没有成功。
更确切地说,我想要实现这里展示的效果: http://vimeo.com/41495357 其中折叠动画不仅仅是简单的动画打开,而是用户控制了打开的折叠动画。
希望能得到任何帮助,提前感谢!
编辑: 以下是一些示例代码,以更好地说明我的问题:
此方法触发Origami效果动画:
- (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值或内容偏移量)来控制效果的进度。

再次感谢您提供的任何帮助!

3个回答

8

非常感谢您的回复,您做得很好,并且感谢您将其公开。 - Ashley Cameron

6

2

这个似乎只提供了“翻页”效果。看看这个视频:http://vimeo.com/41495357,会更清楚我想要的是“折叠”动画。 - Ashley Cameron
我已看过你的编辑(顺便说一下,谢谢),但我仍然无法做到与“DealIn”iOS应用程序示例视频中展示的效果相近。:( - Ashley Cameron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接