【问题标题】:Stumped by math: Adjust alpha based on UIGestureRecognizer panning数学难倒:根据 UIGestureRecognizer 平移调整 alpha
【发布时间】:2012-07-01 23:29:11
【问题描述】:

我很确定这里有一个明显的答案,也许我太累了,看不到它,但这里是:

我有一个UIPanGestureRecognizer。它被连接起来以移动视图。

我在这个视图中有一个子视图,我想在平移视图时调整alpha

视图只能水平平移,这样就省去了一些数学运算。

有问题的子视图以alpha1.0 开头。在超视图平移时,我想调整子视图的 alpha 使其按比例越来越低,直到达到最小值 alpha0.3

我的代码在这一点上并不多,但实际上看起来像这样:

- (void) someMethodForRecognizer: (UIGestureRecognizer *) recognizer {
    // do stuff here

    if (recognizer.state == UIGestureRecognizerStateChanged) {
        // do fancy math here
    }

    // do more stuff here
}

我需要做什么样的数学计算才能在UIGestureRecognizerStateChanged 期间的任何给定时刻应用正确的alpha

(假设相关状态相关的 ivars 已设置且可用,您可以随意添加任何看起来不明显的内容。)

(我真的是个懒惰的白痴,不是吗?)

【问题讨论】:

  • 平移距离和alpha有什么关系?那么当你远离原点时它应该变得更加透明吗?它可以移动的最远距离是多少?您希望它何时达到 0.3 alpha?

标签: cocoa-touch uiview uikit uigesturerecognizer


【解决方案1】:

使用translationInView: 属性找出您已经平移了多远。该点的 x 值是您的水平运动。取它的绝对值,并将其作为您想要给出最小 alpha 的任何距离的比例。将此比例乘以 (1 - minAlpha),从 1.0 中减去它并将子视图的 alpha 设置为此值。

伪代码:

CGPoint translation = [gesture translationInView:self];
CGFloat x = fabsf(translation.x);
CGFloat proportion = x / MIN_ALPHA_DISTANCE;
CGFloat alphaDifference = proportion * (1 - MIN_ALPHA);
subview.alpha = 1 - alphaDifference;

【讨论】:

  • 谢谢,这正是我想要弄清楚的。我用 screen.bounds.size.width 替换了你的 MIN_ALPHA_DISTANCE 以获得我想要的行为,现在它工作得很好! :D
  • 我假设 MIN_ALPHA(不是 MIN_ALPHA_DISTANCE)与 MIN_ALPHA_DISTANCE 相同?在这种情况下,self.view.frame.size.width?
【解决方案2】:

如果您不介意我提出稍微不同的方法,我会使用 NSTimer (+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats)。

- (void) someMethodForRecognizer: (UIGestureRecognizer *) recognizer {
    switch (recognizer.state) {
        case UIGestureRecognizerStateBegan:
            self.panStartTime = CFAbsoluteTimeGetCurrent();
            self.panView = recognizer.view;
            self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                                          target:self
                                                        selector:@selector(panIntervalWithTimer:)
                                                        userInfo:nil
                                                         repeats:YES];
            break;

        case UIGestureRecognizerStateChanged:
            // Your current pan handler
            break;

        default:
            self.panView.alpha = 1.0;
            self.panView = nil;
            self.panStartTime = 0;

            [self.timer invalidate];
            self.timer = nil;
    }
}

- (void)panIntervalWithTimer:(NSTimer *)timer
{
    NSTimeInterval interval = CFAbsoluteTimeGetCurrent() - self.panStartTime;
    CGFloat alpha = 1 - interval; // or some better math
    if (alpha > 0.3) {
        self.panView.alpha = alpha;
    } else {
        self.panView.alpha = 0.3;

        [self.timer invalidate];
        self.timer = nil;
    }
}

更新了计时器内置的无效功能并修复了一些错误。


用新的想法更新了代码。

如何在每次回调时将 alpha 降低一定数量。当用户暂停时,alpha 停止减少。如果速率设置为 0.025,则在达到 0.3 之前会进行 28 次更新。如果速率为 0.001,则提供 70 次更新。

- (void) someMethodForRecognizer: (UIGestureRecognizer *) recognizer {
    …

    if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGFloat alpha = recognizer.view.alpha - kAlphaDecrementRate;
        recognizer.view.alpha = MAX(alpha, 0.3);
    } else {
        recognizer.view.alpha = 1.0;
    }

    …
}

【讨论】:

  • 请原谅我的直言不讳,但我看不出这有什么关系,尽管它很有趣。当我已经进行了实时用户交互时,为什么还需要一个计时器?我希望子视图的 alpha 直接受到用户操作状态的影响。
  • @abrahamvegh 如果你不想使用 NSTimer 也没关系。我会用它一个原因。它将设置 alpha 的次数与平移更新的次数分开。例如,如果用户开始平移,然后静止一秒钟,您可能不会得到任何平移更新。然后所选视图的 alpha 将不会更新。从本质上讲,它可以防止您获得太多或太少的 alpha 更新。
  • 啊,我明白你的意思了。我试图模仿 iOS Springboard 的行为,如果用户停止移动,它会停止 alpha 更改。
  • @abrahamvegh 我添加了一个新想法。
  • 杰弗里·托马斯:谢谢你的想法! @jrturton 正是我所想的,但无法弄清楚要表达的数学。您的方法对其他情况很有用,但对于我的用例来说,它有太多的“神奇数字”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-04
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
相关资源
最近更新 更多