我正在寻找有关如何在我的 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 值或内容偏移量)来控制效果的进度。
再次感谢您提供的任何帮助!