Iphone 方向更改期间平滑的纵横比更改
当iPhone的屏幕方向改变时,我会将3D渲染的投影矩阵调整为新的纵横比值。但是,在Iphone 方向更改期间平滑的纵横比更改,iphone,objective-c,ios,opengl-es-2.0,aspect-ratio,Iphone,Objective C,Ios,Opengl Es 2.0,Aspect Ratio,当iPhone的屏幕方向改变时,我会将3D渲染的投影矩阵调整为新的纵横比值。但是,在willRotateToInterfaceOrientation或didRotateFromInterfaceOrientation中执行此操作将导致过渡期间纵横比错误,因为在动画开始时,屏幕大小仍然与之前相同,并且在旋转时逐渐更改为新边界。因此,我希望用于3D投影矩阵的纵横比值也逐渐改变。为了实现这一点,我在WillAnimateRotationInterfaceOrientation中检索旋转动画的开始时间和
willRotateToInterfaceOrientation
或didRotateFromInterfaceOrientation
中执行此操作将导致过渡期间纵横比错误,因为在动画开始时,屏幕大小仍然与之前相同,并且在旋转时逐渐更改为新边界。因此,我希望用于3D投影矩阵的纵横比值也逐渐改变。为了实现这一点,我在WillAnimateRotationInterfaceOrientation
中检索旋转动画的开始时间和持续时间:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
_aspect.isChanging = YES;
_aspect.startedChanging = [[NSDate date] retain];
_aspect.changeDuration = duration;
_aspect.oldValue = self.renderer.aspect;
_aspect.currentValue = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
}
请注意,视图边界大小已设置为动画后有效的新值
然后,在更新中,我执行以下操作:
- (void)update
{
if (_aspect.isChanging) {
float f = MIN(1, [[NSDate date] timeIntervalSinceDate:_aspect.startedChanging] / _aspect.changeDuration);
self.renderer.aspect = _aspect.oldValue * (1-f) + _aspect.currentValue * f;
} else {
self.renderer.aspect = _aspect.currentValue;
}
[self.renderer update];
}
这已经很好地工作了,但是渲染方面的更改与实际方面的更改不匹配,这是因为我对其进行了线性插值。因此,我试图通过在问题上抛出数学函数来匹配实际方面的变化:我能得到的最佳结果是添加以下行:
f = 0.5f - 0.5f*cosf(f*M_PI);
这导致在旋转过程中几乎没有可见的图像拉伸,但是如果仔细观察,图像之间的某个地方似乎仍然有点不匹配。我想,最终用户不会注意到这一点,但我想问的是,是否有更好的解决方案,以下是我的问题:
- 在旋转更改动画期间,用于纵横比更改的实际缓和功能是什么
- 在方向更改动画期间,是否有方法获取视图显示时的实际宽度和高度?这将允许我直接检索中间方面
KCAMediatiming函数easeineAseOut
)获取定义过渡的曲线的控制点。然后使用三次贝塞尔曲线公式
在第二个要点中,您可以使用
[[view layer]presentationLayer]
获取该视图的CALayer
版本,并根据其当前状态应用所有当前动画。因此,如果您检查其维度,您应该会得到当时的值-我想如果您对CADisplayLink
回调进行操作,那么您最多会落后一帧。在第一个要点上,您可以使用(可能与KCAMediatiming函数easeAseOut
)获取定义过渡的曲线的控制点。然后使用三次贝塞尔曲线公式
在第二个要点中,您可以使用
[[view layer]presentationLayer]
获取该视图的CALayer
版本,并根据其当前状态应用所有当前动画。因此,如果您检查其维度,您应该会得到当时的当前值-我猜如果您对CADisplayLink
回调进行操作,那么您最多会落后一帧。使用presentationLayer
维度的解决方案看起来不错而且干净。我在GLKViewController
的update
方法中更新它,该方法作用于CADisplayLink
。在模拟器的“慢动作”视图中,结果看起来非常完美,但是它似乎落后于设备上的至少一帧,这是可见的,如果你知道的话,但这是可以接受的。我将这样使用它,因为它很简单。使用presentationLayer
维度的解决方案看起来很好而且干净。我在GLKViewController
的update
方法中更新它,该方法作用于CADisplayLink
。在模拟器的“慢动作”视图中,结果看起来非常完美,但是它似乎落后于设备上的至少一帧,这是可见的,如果你知道的话,但这是可以接受的。我将这样使用它,因为它很简单。