0

Я пытаюсь выяснить, как построить ограниченный диапазон значений с плавающей запятой, основанный на скорости UIPanGestureRecognizer. Я имею минимальное или начальное значение 1.0 и максимум 3.0, чтобы предоставить ограниченный диапазон для UIBezierPathlineWidth.UIBezierPath lineWidth на основе скорости UIPanGestureRecognizer

Я пытаюсь выяснить, как построить экспоненциальный диапазон от 1,0 до 3,0, основанный соответственно на скорости UIPanGestureRecognizer, но у меня есть трудное время, когда я должен начать отображение значений. Чем быстрее объединенная скорость 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

Так что я хотел бы использовать перевернутую экспоненциальную функцию.

Начните с скорости, V (x, y). Ваша абсолютная скорость, очевидно, равна:

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

Мы будем называть это значение "v."

Далее мы хотим, чтобы значение находилось между 1 и 3, где 1 - ширина, где «v» очень высокая, а 3 - ширина, где «v» очень низкая.

Мы можем вычислить, что, используя следующую экспоненциальную функцию:

- (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, которую вы смешаете t найти работы красиво:

- (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); 
} 

Мне было бы интересно узнать, какая из них лучше всего работает! Дай мне знать. У меня есть намного больше функций в моем рукаве, это просто некоторые очень простые, которые должны вас начать.

+0

Alex, мне все еще нужно сохранить свойство последней ширины строки, чтобы я мог сгладить линию, проходящую от последней? – klcjr89

+0

Кроме того, я пробовал четыре функции, которые вы создали, только функции getLinearWidthForVelocity и 'getSqrtWidthForVelocity' меняют ширину линии, что я и хочу, остальные две функции остаются статическими размерами, даже играя с' rootConstantYouCanAdjust' (установите его на 80000) и не изменили ширину линии. – klcjr89

+0

Упс. совершил ошибку там. Должно быть 2/v и 2/(pow (v, rootConstantYouCanAdjust)) соответственно вместо 1 в числителе. Что касается сохранения предыдущего значения, просто используйте: @ property (nonatomic) CGFloat previousWidth; в вашем интерфейсе @ и просто перезагружайте его каждый раз, когда вы вызываете функцию, которая обновляет строку. – AlexKoren