Future release in 3D rotation

I want to achieve something like this:

enter image description here

What is a snapshot of my view controller

The code I tried looks like this:

UIWindow *window = [[UIApplication sharedApplication] keyWindow]; // Take a snapshot // _screenshotView = [[UIImageView alloc] initWithFrame:CGRectNull]; _screenshotView.image = [self getScreenSnapshot]; _screenshotView.frame = CGRectMake(-160, -284, _screenshotView.image.size.width, _screenshotView.image.size.height); _screenshotView.userInteractionEnabled = YES; _screenshotView.layer.anchorPoint = CGPointMake(0, 0); _originalSize = _screenshotView.frame.size; [window addSubview:_screenshotView]; [self minimizeFromRect:CGRectMake(0, 0, _originalSize.width, _originalSize.height)]; - (void)minimizeFromRect:(CGRect)rect { UIWindow *window = [[UIApplication sharedApplication] keyWindow]; CGFloat m = 0.7; CGFloat newWidth = _originalSize.width * m; CGFloat newHeight = _originalSize.height * m; [CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:0.6] forKey:kCATransactionAnimationDuration]; [self addAnimation:@"position.x" view:_screenshotView startValue:rect.origin.x endValue:window.frame.size.width - 80.0]; [self addAnimation:@"position.y" view:_screenshotView startValue:rect.origin.y endValue:(window.frame.size.height - newHeight) / 2.0]; [self addAnimation:@"bounds.size.width" view:_screenshotView startValue:rect.size.width endValue:newWidth]; [self addAnimation:@"bounds.size.height" view:_screenshotView startValue:rect.size.height endValue:newHeight]; _screenshotView.layer.position = CGPointMake(window.frame.size.width - 80.0, (window.frame.size.height - newHeight) / 2.0); _screenshotView.layer.bounds = CGRectMake(window.frame.size.width - 80.0, (window.frame.size.height - newHeight) / 2.0, newWidth, newHeight); CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; rotationAndPerspectiveTransform.m34 = 1.0 / -600; rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, -20.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f); _screenshotView.layer.transform = rotationAndPerspectiveTransform; [CATransaction commit]; } 

The code works just fine, except that it looks like the rotation is shown from a different perspective, because the snapshot after the animation looks like this:

enter image description here

What am I missing?

+6
source share
2 answers

Solved by replacing the UIImageView object with a CALayer layer CALayer . Thanks https://github.com/kristopherjohnson/perspectivetest

  UIWindow *window = [[UIApplication sharedApplication] keyWindow]; // Take a snapshot // UIImage *image = [self getScreenSnapshot]; CGImageRef pictureImage = image.CGImage; CGFloat zDistance = 1200.0f; CATransform3D transform = CATransform3DIdentity; transform.m34 = 1.0f / -zDistance; _screenshotView = [[UIView alloc] initWithFrame:CGRectNull]; _screenshotView.frame = CGRectMake(0, 0, image.size.width, image.size.height); _screenshotView.userInteractionEnabled = YES; _imageLayer = [CALayer layer]; _imageLayer.frame = _screenshotView.frame;; _imageLayer.contents = (__bridge id)pictureImage; _imageLayer.transform = transform; [_screenshotView.layer addSublayer:_imageLayer]; _originalSize = _screenshotView.frame.size; [window addSubview:_screenshotView]; [self minimizeFromRect:CGRectMake(0, 0, _originalSize.width, _originalSize.height)]; - (void)minimizeFromRect:(CGRect)rect { UIWindow *window = [[UIApplication sharedApplication] keyWindow]; CGFloat m = 0.6; CGFloat newWidth = _originalSize.width * m; CGFloat newHeight = _originalSize.height * m; [CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:0.4] forKey:kCATransactionAnimationDuration]; [self addAnimation:@"position.x" view:_screenshotView startValue:rect.origin.x endValue:window.frame.size.width - 40.0]; [self addAnimation:@"position.y" view:_screenshotView startValue:rect.origin.y endValue:(window.frame.size.height - newHeight) / 2.0]; [self addAnimation:@"bounds.size.width" view:_screenshotView startValue:rect.size.width endValue:newWidth]; [self addAnimation:@"bounds.size.height" view:_screenshotView startValue:rect.size.height endValue:newHeight]; [self addAnimationForLayer:@"transform.rotation.y" view:_imageLayer startValue:0.0f endValue:-0.4 * M_PI]; _screenshotView.layer.position = CGPointMake(window.frame.size.width - 80.0, (window.frame.size.height - newHeight) / 2.0); _screenshotView.layer.bounds = CGRectMake(window.frame.size.width - 80.0, (window.frame.size.height - newHeight) / 2.0, newWidth, newHeight); [CATransaction commit]; } 
0
source

One way may be that you can use two images: one for the upper half and one for the lower half. And you can stitch two images together so that the gap is not visible, and you can get the desired result.

Set the property for one positive and one negative value for the top and bottom images, or vice versa. You can get two images of the desired result. Then you can set the frame so that they stick together so that they look like a single image.

Property :: rotationAndPerspectiveTransform.m34 = 1.0 / 600.0;

Property :: rotationAndPerspectiveTransform.m34 = -1.0 / 600.0;

You may need to make a hit and a trial version.

0
source

Source: https://habr.com/ru/post/949795/


All Articles