【问题标题】:How to animate CGAffineTransform smoothly as drag gesture is performed如何在执行拖动手势时平滑地为 CGAffineTransform 设置动画
【发布时间】:2013-04-17 18:21:49
【问题描述】:

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

希望这是有道理的。作为一个虚拟的例子,想象一个滑块,你可以调整它来实时改变 UIView 的大小。有没有一种使用CGAffineTransform 进行此类增量和恒定大小更新的好方法?

【问题讨论】:

    标签: iphone ios cgaffinetransform uipangesturerecognizer


    【解决方案1】:

    在您的平移手势处理程序中,您只需抓住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 计算,但希望您能明白这一点。

    就我个人而言,我宁愿使用捏合手势识别器来调整大小(它是用户接受过培训的 UI,它为您提供了开箱即用的 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);
        }
    }
    

    【讨论】:

    • 完美 - 对我来说缺少的链接是始终将转换应用于您所谓的 originalTransform 的想法,所以我现在进展顺利。我同意在大多数情况下,捏合手势当然对缩放最有意义。然而,在这种情况下,我正在尝试在视图之间转换的创造性方法,而这种比例实际上只是拖动触发转换期间的一种奇特的副作用。非常感谢您的详尽回答!
    【解决方案2】:

    我发现最好的方法是使用 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 替换为圆圈的初始位置。

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

    【讨论】:

    • 你应该认真提一下:什么是 widthOfCircle ?否则不要指望投票..
    猜你喜欢
    • 2012-12-03
    • 2016-06-27
    • 2023-03-13
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    相关资源
    最近更新 更多