当iPhone方向的屏幕发生变化时,我将3D渲染的投影矩阵调整为新的方位值。但是,在willRotateToInterfaceOrientation
或didRotateFromInterfaceOrientation
中执行此操作会导致在转换期间宽高比错误,因为在动画开始时,屏幕大小仍然与以前相同并且更改为旋转时逐渐出现新界限。因此,我希望用于3D投影矩阵的方位值也会逐渐变化。为此,我在willAnimateRotationToInterfaceOrientation
中检索旋转动画的开始时间和持续时间:
- (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);
}
请注意,视图边界大小已设置为在动画后有效的新值。
然后,在update
中,我执行以下操作:
- (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);
这导致在旋转期间几乎没有可见的图像拉伸,但是如果仔细观察,它之间似乎仍然有点无法比拟。我想,最终用户不会注意到它,但我在这里问是否有更好的解决方案,所以这些是我的问题:
答案 0 :(得分:3)
在第一个项目符号点上,您可以使用CAMediaTimingFunction
(可能带有kCAMediaTimingFunctionEaseInEaseOut
)来获取定义过渡的曲线的控制点。然后使用三次贝塞尔曲线公式。
在第二个要点上,您可以使用[[view layer] presentationLayer]
获取该视图CALayer
的版本,并根据当前状态应用所有当前动画。因此,如果你检查它的尺寸,你应该获得当前的值 - 我想如果你对CADisplayLink
回调采取行动,那么你最多只能落后一帧。