我正在做一些实验来学习iOS中的手势和动画。创建类似Tinder的界面就是其中之一。我正在遵循本指南:http://guti.in/articles/creating-tinder-like-animations/
我理解图像位置的变化,但不了解旋转。我想我已经指出我的问题是不理解CGAfflineTransform。特别是,以下代码:
CGFloat rotationStrength = MIN(xDistance / 320, 1);
CGFloat rotationAngle = (CGFloat) (2 * M_PI * rotationStrength / 16);
CGFloat scaleStrength = 1 - fabsf(rotationStrength) / 4;
CGFloat scale = MAX(scaleStrength, 0.93);
CGAffineTransform transform = CGAffineTransformMakeRotation(rotationAngle);
CGAffineTransform scaleTransform = CGAffineTransformScale(transform, scale, scale);
self.draggableView.transform = scaleTransform;
这些值和计算在哪里,例如:320,1-fabs(强度)/ 4,.93等来自哪里?他们如何为最终轮换做出贡献?
另一方面,Tinder似乎使用了滑动和平移的组合。他们是否向图像添加了滑动手势,还是只考虑了平移的速度?
答案 0 :(得分:0)
该代码有很多magic constants,其中大多数都可能被选中,因为它们产生了“看起来不错”的东西。这可能使其难以遵循。它不是关于实际的变换,而是关于用于创建它们的值。
让我们逐行分解,看看是否能让它更清晰。
CGFloat rotationStrength = MIN(xDistance / 320, 1);
值320
可能被假设为设备的宽度(它是所有iPhone的纵向宽度,直到6和6+出现)。
这意味着xDistance / 320
是沿x轴的距离(基于用户拖动的名称xDistance)
)的一个因素。当用户未拖动任何内容时,这将是0.0当用户拖动320点时距离和1.0。
MIN(xDistance / 320, 1)
取拖动距离因子的最小值1)。这意味着如果用户拖动超过320点(因此距离系数将大于1,旋转强度将永远不会大于1.0。它不会再次保护负值(如果用户拖动到左侧, xDistance是一个负值,它总是小于1.但是,我不确定指南是否占了这个(因为320是全宽,而不是半宽。
因此,第一行是应该应用多少旋转的0到1之间的因子(假设没有负值)。
CGFloat rotationAngle = (CGFloat) (2 * M_PI * rotationStrength / 16);
下一行计算实际旋转角度。角度以弧度指定。由于2π是整圆(360°),因此旋转角度在整圆(22.5°)的0和1/16之间。可能选择值1/16
,因为它“看起来很好”。
这两行共同意味着当用户进一步拖动时,视图会旋转得更多。
CGFloat scaleStrength = 1 - fabsf(rotationStrength) / 4;
从变量名称看,它会计算出视图应该缩放的程度。但实际上它正在计算视图应具有的比例因子。比例为1表示“正常”或未缩放的大小。当旋转强度为0时(当xDistance为0时),刻度强度将为1(未缩放)。随着旋转强度增加,接近1,这个比例因子接近0.75(因为那是1 - 1/4)。
fabsf
只是浮点绝对值(fabsf(-0.3)
等于0.3
)
CGFloat scale = MAX(scaleStrength, 0.93);
在下一行,计算实际比例因子。它只是scaleStrength的最大值和0.93(缩小到93%)。值0.93
完全是任意的,可能正是作者发现的吸引力。
由于比例强度范围为1到0.75且比例因子从不小于0.93,因此比例因子仅在xDistance的前三分之一处变化。接下来三分之二的所有比例强度值都将小于0.93,因此不会改变比例因子。
如上所述计算scaleFactor和rotationAngle,首先旋转视图(按该角度),然后按比例缩小(按比例因子)。
所以,简而言之。当视图向右拖动时(xDistance接近320点),视图在整个拖动过程中从0°线性旋转到22.5°,并在拖动的前三分之一从100%缩放到93%(然后停留在拖动手势的其余部分为93%。