0

我一直在玩斯坦福大学讲座/WWDC 视频,该视频向您展示了如何创建同时捏/缩放的手势。它返回一个CGAffineTransform然后你应用到 UIView。

这一切都很好,但我试图让它更流畅一些,并为代码添加一些减速。我试图通过在每次UIGestureRecognizerStateChanged调用时存储转换矩阵来做到这一点,然后当我收到时,UIGestureRecognizerStateEnded我存储最后一个 Changed 和 Ended 矩阵之间的增量:

- (void)handleTransform:(TransformGestureRecognizer *)transformRecognizer
{
    CGAffineTransform transform = transformRecognizer.transform;

    // cancel any previous animation updates
    [UIView cancelPreviousPerformRequestsWithTarget:self selector:@selector(decelerateView:) object:transformRecognizer.view];

    if(transformRecognizer.state == UIGestureRecognizerStateBegan)
    {
        transform = CGAffineTransformConcat(transformRecognizer.view.transform, transform);
        transformRecognizer.transform = transform;
    }
    else if(transformRecognizer.state == UIGestureRecognizerStateChanged)
    {
        changingTransform = transform;
    }
    else if(transformRecognizer.state == UIGestureRecognizerStateEnded)
    {
        // get transform difference
        releaseTransformDiff.a = (transform.a - changingTransform.a);
        releaseTransformDiff.b = (transform.b - changingTransform.b);
        releaseTransformDiff.c = (transform.c - changingTransform.c);
        releaseTransformDiff.d = (transform.d - changingTransform.d);
        releaseTransformDiff.tx = (transform.tx - changingTransform.tx);
        releaseTransformDiff.ty = (transform.ty - changingTransform.ty);

        // start updating deceleration animation
        [self performSelector:@selector(decelerateView:) withObject:transformRecognizer.view afterDelay:1.0/60.0];
    }

    transformRecognizer.view.transform = transform;
}

然后,我有一个decelerateView:动画减速的方法:

#define DECELERATION_RATE 0.9

- (void)decelerateView:(UIView *)view
{
    releaseTransformDiff.a = releaseTransformDiff.a * DECELERATION_RATE;
    releaseTransformDiff.b = releaseTransformDiff.b * DECELERATION_RATE;
    releaseTransformDiff.c = releaseTransformDiff.c * DECELERATION_RATE;
    releaseTransformDiff.d = releaseTransformDiff.d * DECELERATION_RATE;
    releaseTransformDiff.tx = releaseTransformDiff.tx * DECELERATION_RATE;
    releaseTransformDiff.ty = releaseTransformDiff.ty * DECELERATION_RATE;

    view.transform = CGAffineTransformMake(view.transform.a + releaseTransformDiff.a, 
                                           view.transform.b + releaseTransformDiff.b, 
                                           view.transform.c + releaseTransformDiff.c, 
                                           view.transform.d + releaseTransformDiff.d, 
                                           view.transform.tx + releaseTransformDiff.tx,
                                           view.transform.ty + releaseTransformDiff.ty);
    [self performSelector:@selector(decelerateView:) withObject:view afterDelay:1.0/60.0];
}

这有时有效,但有时它会突然停止,并且几乎从不减慢我所做的任何旋转旋转......我想我没有正确计算两个矩阵的增量。这样做的正确方法是什么?

4

1 回答 1

1

CGAffineTransformation 是表示 3 x 3 矩阵的简化数据结构:

|a  b  0|
|c  d  0|
|tx ty 1|

通过将 3 x 1 矩阵乘以上述矩阵来变换一个点

                      |a  b  0|
[x' y' 1] = [x y 1] X |c  d  0|
                      |tx ty 1|

要创建缩放仿射变换,请将 a 设置为缩放 x 轴的因子,并将 d 设置为缩放 y 轴的因子。要创建平移仿射变换,请将 tx 设置为沿 x 轴移动的值,将 ty 设置为沿 y 轴移动的值。

此问题中使用的技术适用于仅是缩放或平移变换(或这两种类型的变换的组合)的仿射变换。那是因为受影响的四个值确实线性且独立地变化。

为了创建角度 A 的旋转仿射变换,将 a 设置为 cos A,b 设置为 sin A,c 设置为 -sin A,d 设置为 cos A。由于 sin 和 cos 不是线性函数,因此问题中提出的增量变化将不能正常工作。更复杂的是,两个变换的组合是表示这些变换的两个矩阵的乘积。在涉及旋转的情况下,生成的矩阵不会与会导致变换略有不同的矩阵线性不同。

构建增量转换的方法是更改​​转换构建函数调用的输入,而不是直接使用结果矩阵。

于 2012-05-08T18:45:36.617 回答