objective-c - 折叠动画与滑动动画不对齐

标签 objective-c ios core-animation

我正在尝试创建一个像这样的折叠菜单动画:http://vimeo.com/41495357

此时,当您在屏幕上拖动手指时动画有效,但是当我尝试将菜单设置为从打开到关闭或关闭到直接打开的动画时,滑开的主视图与右侧不对齐正在展开的 View 。它们在动画结束时对齐,但在动画结束时不对齐。此外,正在展开的 View 的边缘似乎在动画期间消失在 View 的边界之外。

层的实际展开是在 layoutSublayers 中完成的,因此当层的宽度发生变化时,将计算其子层上的变换。我在这个项目中找到了计算转换的数学方法: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);

这是负责启动展开动画的代码。 (现在菜单展开到屏幕的整个宽度)

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);

为什么这些动画不对齐?也许数学不正确?我查看了来自 https://github.com/honcheng/PaperFold-for-iOS 等项目的示例代码和 https://github.com/xyfeng/XYOrigami但我想不通。

更新

根据 Till 的回答,我为滑动层创建了这个关键帧动画。动画仍然没有对齐,所以我的关键帧计算一定是错误的?

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"];

最佳答案

我认为您是从错误的方向解决问题的。你想计算距离的角度,而不是相反。如果你想计算折叠动画每一边的角度,你可以使用基本的毕达哥拉斯算术。很明显,我们知道打开距离的大小,也知道斜边的大小(完全打开时 View 大小的一半)。

在代码中:

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;

您可以使用这些角度来设置折叠 View 左侧和右侧的旋转。

注意将左侧的 anchor 设置为 (0.0, 0,5) 并将右侧的 anchor 设置为 (1.0, 0.5) 并为右侧平移设置动画!

希望对您有所帮助!干杯!

关于objective-c - 折叠动画与滑动动画不对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12706666/

相关文章:

animation - 如何知道 coreanimation 动画何时结束

iphone - 在 iPhone 上滚动时重复图像

ios - 将 tapku 日历添加到 ios 应用程序

ios - 使用AVFoundation录制方形视频并添加水印

iphone - CoreAnimation CALayer 和 CATextLayer 组合

ios - 淡入淡出动画

objective-c - 如何返回两个值?

ios - 从 Controller 内的页面更改 PageViewController 中的页面?

ios - 在 Core Data 中执行子提取时,修改父上下文中的托管对象是否会向下传播到子上下文?

iphone - .mobileconfig 文件有什么用?