如何在执行拖动手势时平滑地动画CGAffineTransform

时间:2013-04-17 18:21:49

标签: iphone ios cgaffinetransform uipangesturerecognizer

我理解检测拖动手势的各种方法很好(目前我正在使用UIPanGestureRecognizer),但我对转换的理解是有限的,所以我不确定这是否可行。基本上,我想要的是当用户在屏幕上的其他位置执行拖动手势时,以相同的步速(由于缺少更好的词)应用于UIView的缩放变换。换句话说,当用户拖动时,我希望我的变换UIView的大小与该手势的位置成比例增加,如果用户然后开始向下拖动,它应该开始按比例缩小。

希望这是有道理的。作为一个虚拟示例,想象一下您可以调整的滑块,以实时更改UIView的大小。是否有一种很好的方法可以使用CGAffineTransform进行那些增量和常量大小更新?

2 个答案:

答案 0 :(得分:3)

在您的平移手势处理程序中,您只需抓取translationInViewlocationInView,从中计算出一个比例,然后相应地更新转换。例如:

- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static CGAffineTransform originalTransform;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalTransform = self.viewToScale.transform;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [gesture translationInView:gesture.view];
        CGFloat scale = 1.0 - translation.y / 160.0;
        self.viewToScale.transform = CGAffineTransformScale(originalTransform, scale, scale);
    }
}

你可以根据你想要做的事情来进行scale计算,但希望你明白这一点。

就个人而言,我宁愿使用捏手势识别器进行大小调整(这是用户已经过训练的用户界面,它可以提供开箱即用的scale因子等),但无论如何都有效为了你。如果你做了捏手势识别器,它可能看起来像:

- (void)handlePinch:(UIPinchGestureRecognizer *)gesture
{
    static CGAffineTransform originalTransform;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalTransform = self.viewToScale.transform;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        self.viewToScale.transform = CGAffineTransformScale(originalTransform, gesture.scale, gesture.scale);
    }
}

答案 1 :(得分:0)

我发现最好的方法是使用locationInView,这样就可以将位置偏移(以像素为单位)与刻度相等。例如,如果圆圈位于视图的中心:

func dragDot(recognizer: UIPanGestureRecognizer) {

    let locationX = recognizer.location(in: self.view).x

    // Expand and contract the circle
    let locationXOffset = locationX - self.view.center.x

    // We need scale to be 1 when locationXOffset = circle radius
    let scale: CGFloat = locationXOffset / (self.widthOfCircle / 2)

    self.ring.transform = CGAffineTransform(scaleX: scale, y: scale)
}

如果圆圈不在视图的中心,则将self.view.center.x替换为圆圈的初始位置。

此方法适用于所有设备和屏幕分辨率,并且无需校准常量