Folding animation does not line up with unfolding animation

I am trying to create a bend menu animation similar to this one: http://vimeo.com/41495357

At this point, the animation works by dragging my finger across the screen, but when I try to animate a menu from open to closed or closed to open it directly, the main view that slides does not align with the right side of the expand. They are aligned when the animation ends, but not during. In addition, the edges of the expanded view appear to disappear beyond the scope of the animation.

The actual deployment of the layer is done in layoutSublayers, so when the width of the layer changes, transformations on its sublayers are calculated. I found the math to calculate the transformations in this project: https://github.com/MassiveHealth/Opaque

// Configure the layer bounds and midpoints CGRect halfRect = CGRectMake(0, 0, self.fullWidth / 2, self.bounds.size.height); self.rightImageLayer.bounds = halfRect; self.leftImageLayer.bounds = halfRect; CGPoint midPoint = CGPointMake(0.5 * self.bounds.size.width, 0.5 * self.bounds.size.height); self.rightImageLayer.position = midPoint; self.leftImageLayer.position = midPoint; // Calculate transforms CGFloat l = 0.5 * self.fullWidth; CGFloat y = 0.5 * self.bounds.size.width; CGFloat theta = acosf(y/l); CGFloat z = l * sinf(theta); CGFloat topAngle = theta * -1; CGFloat bottomAngle = theta; CATransform3D transform = CATransform3DMakeTranslation(0.0, 0.0, -z); self.rightImageLayer.transform = CATransform3DRotate(transform, topAngle, 0.0, 1.0, 0.0); self.leftImageLayer.transform = CATransform3DRotate(transform, bottomAngle, 0.0, 1.0, 0.0); 

This is the code that is responsible for running the expandable animation. (right now the menu is expanding to the full width of the screen)

 self.foldingLayer.frame = self.view.bounds; self.slidingLayer.frame = CGRectMake(self.view.frame.size.width, 0, self.slidingLayer.frame.size.width, self.slidingLayer.frame.size.height); 

Why don't these animations line up? Is the math wrong? I looked at the sample code from projects such as https://github.com/honcheng/PaperFold-for-iOS and https://github.com/xyfeng/XYOrigami , but I can not understand.

Update

Depending on the answer to this question, I created a keyframe animation for the moving layer. The animation is still not lining up, so should my keyframe calculations be wrong?

 CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"]; NSUInteger steps = 100; CGFloat totalFoldViewWidth = self.view.bounds.size.width; NSMutableArray *values = [NSMutableArray arrayWithCapacity:steps]; for(NSUInteger i = 0; i < steps; i++) { CGFloat fraction = (CGFloat)i / steps; CGFloat foldViewWidth = fraction * totalFoldViewWidth; CGFloat l = 0.5 * totalFoldViewWidth; CGFloat y = 0.5 * foldViewWidth; CGFloat angle = acosf(y/l); CGFloat projectionWidth = cosf(angle) * totalFoldViewWidth; [values addObject:[NSNumber numberWithFloat:projectionWidth]]; } animation.calculationMode = kCAAnimationLinear; [animation setValues:values]; [animation setDuration:3.0]; [self.slidingLayer addAnimation:animation forKey:@"slideAnimation"]; 
+4
source share
2 answers

I think you are addressing the problem in the wrong direction. You want to calculate angles from a distance, not the other way around. If you want to calculate the angle for each side of the bending animation, you use the basic pythagorean arithmetic. It is clear that we know the size for the opening distance, and we know the size for the hypotenuse (half the size of the view when fully open).

In code:

 CGFloat otherSide = 0.5 * openingWidth; // halve because we have two sides CGFloat hypotenuse = 0.5 * unfoldedViewTotalWidth; // halve because we have to sides CGFloat angle = asinf(otherSide / hypotenuse); CGFloat rightAngle = -1 * (M_PI_2 - angle); CGFloat leftAngle = M_PI_2 - angle; 

You can use these angles to set the rotation for the left and right sides of the bend view.

Beware of setting your anchor points for the left side (0,0, 0,5) and for the right on (1.0, 0.5) and also animate the right shift!

Hope this helps! Hooray!

+3
source

This is really a math problem. The distance of this view depends on the width of the projection of the folded view. This width is not strictly linear depending on the angle;

projectionWidth = cos(angle) * foldViewWidth

In other words, 40 degrees leads to something completely different from 20 degrees, and this ratio is not linear, but based on the cosine of this angle.

Consequently, linear animation will not. You will need to create a frame animation based on the projection width of this folded view to match the translation with rotation.

0
source

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


All Articles