CGAffineTransformScale不适用于零刻度 [英] CGAffineTransformScale not working with zero scale

查看:189
本文介绍了CGAffineTransformScale不适用于零刻度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新到iOS 8,我注意到了一个有趣的问题。我使用CGAffineTransformScale将图像视图缩放到零,这个想法是它从用户的视图中整齐地消失了。这是iOS8的工作,但现在它根本没有。视线瞬间消失;空白!



原来我用过:

  CGAffineTransform zoom = CGAffineTransformScale (CGAffineTransformIdentity,0.0f,0.0f); 
myImageView.transform = zoom;

为什么到目前为止不起作用以及函数何时没有折旧? / p>

解决方案

A CGAffineTransform 是一个3x3矩阵,其最右边的列永久设置至(0,0,1) T 。所以它实际上存储了六个值,它们称之为 a,b,c,d,tx, ty 。前四个控制旋转,缩放和倾斜。最后两个控件转换。



您可能认为从转换 T 动画转换 U 是一个简单的分量插值问题: Ta Ua Tb Ub 等等(我称之为简单插值。)



你错了。



好的,请坚持我。这个解释似乎很迂回但我保证到最后你会理解为什么零刻度会破坏动画。



这是一个我掀起的演示应用程序。它仅在身份变换和160˚旋转之间进行插值(180˚)。





注意两件事:图像缩小然后扩展,它没有均匀的角速度。旋转开始缓慢,加速,然后再次减速。那不是我生涩的手部动作;它使用简单的插值实际上就是这样。



那么这里发生了什么?让我们看看中途的变换(80˚):





在文本中:

[0.030153692,0.17101011,-0.17101011,0.030153692,0,0 ]



80˚的旋转变换应该是什么样的?像这样:

[0.17364822,0.98480773,-0.98480773,0.17364822,0,0]



<你可能已经注意到了,那些矩阵是完全不同的。仅表示旋转的变换具有以下几个属性: a * a + b * b == 1 a == d b == -c 。真正的旋转矩阵具有所有这些属性,但简单插值矩阵却没有。具体来说,它的 a * a + b * b == .030153695 ,这与1相差很远。这意味着它不仅代表旋转,还代表缩放。



这意味着,一般来说,不能只是简单地在两个变换之间进行插值并获得不错的结果。因此系统会做一些更复杂的事情。



核心动画将变换分解为四个部分:旋转角度,比例因子,剪切因子和平移。它插入这些部分,并使用插值来计算动画的中间变换。



OK,你说,但是它有什么用用零刻度矩阵打破动画?



你可以找到分解矩阵的数学在此mathoverflow Q& A中。请注意,要计算旋转角度和剪切因子,您需要除以矩阵的至少一个分量(答案中的A 11 或A 21 a b in CGAffineTransform )。但是,当您按比例缩放零时,这些组件将变为零。你不能除以零。



因此,当系统试图分解你的转换时,它就会失败,它会放弃。



我不是说这是良好的行为,但这是我们的行为。


Updating to iOS 8 and I've noticed an interesting one. I use CGAffineTransformScale to scale an image view to zero, the idea being that it disappears from the user's view neatly. It's work up to iOS8 but now it's not at all. Instantly the view is gone; blank!

So originally I used:

CGAffineTransform zoom = CGAffineTransformScale(CGAffineTransformIdentity, 0.0f, 0.0f);
myImageView.transform = zoom;

Why would this which worked up to now not work and when the functions haven't been depreciated?

解决方案

A CGAffineTransform is a 3x3 matrix, with its rightmost column permanently set to (0, 0, 1)T. So it actually stores six values, which it calls a, b, c, d, tx, and ty. The first four control rotation, scaling, and skewing. The last two control translation.

You might think that animating from transform T to transform U is a simple matter of component-wise interpolation: T.a to U.a, T.b to U.b, etc. (I'll call this "simple interpolation".)

You would be wrong.

OK, stick with me here. This explanation is going to seem circuitous but I promise by the end you'll understand why the zero scale breaks animation.

Here's a demo app I whipped up. It interpolates simply between the identity transform and a 160˚ rotation (not 180˚).

Notice two things: the image shrinks and then expands, and it doesn't have uniform angular velocity. The rotation starts slow, speeds up, and then slows down again. That's not my jerky hand motion; it really behaves that way using simple interpolation.

So what's going on here? Let's look at the transform halfway through (at 80˚):

In text:
[0.030153692, 0.17101011, -0.17101011, 0.030153692, 0, 0]

What should a rotation transform for 80˚ look like? Like this:
[0.17364822, 0.98480773, -0.98480773, 0.17364822, 0, 0]

As you might have noticed, those matrices are rather different. A transform that represents only a rotation has several properties: a*a + b*b == 1, a == d, and b == -c. The true rotation matrix has all of these properties, but the simply-interpolated matrix doesn't. Specifically, its a*a + b*b == .030153695, which is pretty far from 1. This means it represents not just rotation, but scaling.

This means that, in general, you can't just interpolate simply between two transforms and get decent results. So the system does something more complicated.

Core Animation decomposes the transform into four parts: a rotation angle, a scale factor, a shear factor, and a translation. It interpolates these parts, and uses the interpolated values to compute the intermediate transforms of the animation.

"OK", you're saying, "but what does this have to do with a zero-scale matrix breaking the animation?"

You can find the math for decomposing the matrix in this mathoverflow Q&A. Notice that to compute the rotation angle and the shear factor, you need to divide by at least one component of the matrix (A11 or A21 in that answer, a or b in CGAffineTransform). But when you scale by a factor of zero, those components become zero. You can't divide by zero.

So when the system tries to decompose your transform, it fails, and it gives up.

I'm not saying this is good behavior, but it's the behavior we live with.

这篇关于CGAffineTransformScale不适用于零刻度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆