UIBezierPath lineWidth基于UIPanGestureRecognizer的速度

时间:2015-04-08 02:13:15

标签: ios objective-c uigesturerecognizer uibezierpath uipangesturerecognizer

我试图弄清楚如何根据UIPanGestureRecognizer的速度构建有限范围的浮点值。我的最小值或起始值为1.0,最大值为3.0,以便为UIBezierPath lineWidth属性提供有限的范围。

我试图弄清楚如何根据UIPanGestureRecognizer的速度建立一个从1.0到3.0的指数范围,但是我很难开始进行映射价值。组合的x和y速度越快,线宽应该越小(低至1.0),并且如果组合速度越慢则分别相反,高达3.0。我还试图通过存储lastWidth属性来逐渐缩小/平滑正在进行的线宽,以便子路径之间的转换不明显。

我感谢所提供的任何帮助。

基于答案的工作和最终代码:

@property (nonatomic, assign) CGFloat lastWidth;

if (recognizer.state == UIGestureRecognizerStateChanged)
{
    CGPoint velocity = [recognizer velocityInView:self.view];

    CGFloat absoluteVelocity = 1000.0 / sqrtf(pow(velocity.x, 2) + pow(velocity.y, 2));

    CGFloat clampedVel = MAX(MIN(absoluteVelocity, 3.0), 1.0);

    if (clampedVel > self.lastWidth)
    {
        clampedVel = self.lastWidth + 0.15;
    }
    else if (clampedVel < self.lastWidth)
    {
        clampedVel = self.lastWidth - 0.15;
    }

    self.lastWidth = clampedVel;

    UIBezierPath *path = [UIBezierPath bezierPath];
    path.lineCapStyle = kCGLineCapRound;
    path.lineWidth = self.lastWidth;
}

1 个答案:

答案 0 :(得分:1)

所以我使用倒指数函数。

从你的速度V(x,y)开始。你的绝对速度显然是:

sqrt(pow(x, 2) + pow(y, 2));

我们将此值称为&#34; v。&#34;

接下来,我们想要一个介于1和3之间的值,其中1是宽度,其中&#34; v&#34;非常高,3是宽度,其中&#34; v&#34;非常低。

我们可以使用以下指数函数来计算:

- (CGFloat)getExponentialWidthForVeloctity(CGFloat)v {
    if (v <= 1 / 3.0)
        return 3;
    CGFloat inverse = 1 / v;
    return 1 + inverse;
}

或者这个功能可以将它平滑一点

- (CGFloat)getExponentialRootWidthForVeloctity(CGFloat)v {
    //play with this value to get the feel right
    //The higher it is, the faster you'll have to go to get a thinner line
    CGFloat rootConstantYouCanAdjust = 2;
    if (pow(v, rootConstantYouCanAdjust) <= 1 / 3.0)
        return 3;
    CGFloat inverse = 1 / pow(v, rootConstantYouCanAdjust);
    return 1 + inverse;
}

如果感觉不对,请尝试线性解决方案:

- (CGFloat)getLinearWidthForVelocity(CGFloat)v {
    //Find this value by swiping your finger really quickly and seeing what the fastest velocity you can get is
    CGFloat myExpectedMaximumVelocity = 1000; 
    if (v > myExpectedMaximumVelocity)
        v = myExpectedMaximumVelocity;
    return 3 - 2 * (v / myExpectedMaximumVelocity);
}

最后,作为奖励,尝试这个基于sqrt的功能,你可能会觉得很好用:

- (CGFloat)getSqrtWidthForVelocity(CGFloat)v {
    //find the same way as above
    CGFloat myExpectedMaximumVelocity = 1000;
    if (v > myExpectedMaximumVelocity)
        return 1;
    return 3 - 2 * sqrt(v) / sqrt(myExpectedMaximumVelocity);
}

我很想知道哪种方法效果最好!让我知道。我有更多的功能,这些只是一些非常简单的功能,应该让你开始。