UITouch移动速度检测

时间:2009-03-20 22:37:31

标签: iphone objective-c

我正在尝试检测触摸移动的速度,但我并不总能得到我期望的结果。 (补充说:速度激增太多了) 如果我正在做一些时髦的事情或提出更好的做法,有人能发现吗?


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.previousTimestamp = event.timestamp;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    CGPoint prevLocation = [touch previousLocationInView:self.view];
    CGFloat distanceFromPrevious = distanceBetweenPoints(location,prevLocation);
    NSTimeInterval timeSincePrevious = event.timestamp - self.previousTimestamp;
    CGFloat speed = distanceFromPrevious/timeSincePrevious;
    self.previousTimestamp = event.timestamp;
    NSLog(@"dist %f | time %f | speed %f",distanceFromPrevious, timeSincePrevious, speed);

}

3 个答案:

答案 0 :(得分:11)

你可以尝试(在touchesBegan中将distanceSinceStart和timeSinceStart归零):

distanceSinceStart = distanceSinceStart + distanceFromPrevious;
timeSinceStart = timeSincestart + timeSincePrevious;
speed = distanceSinceStart/timeSinceStart;

这将为您提供自开始触摸以来的平均速度(总距离/总时间)。

或者你可以做一个移动平均速度,也许是一个指数移动平均线:

const float lambda = 0.8f; // the closer to 1 the higher weight to the next touch

newSpeed = (1.0 - lambda) * oldSpeed + lambda* (distanceFromPrevious/timeSincePrevious);
oldSpeed = newSpeed;

如果要为最近的值赋予更多权重,可以将lambda调整为接近1的值。

答案 1 :(得分:3)

主要问题是当timeSincePrevious非常小(几毫秒)时,速度计算将非常不准确。要看到这一点,我们假设timeSincePrevious是1毫秒。如果distanceFromPrevious为0,则计算出的速度为0;如果distanceFromZero为1,则计算速度为1000。

出于这个原因,我建议使用以下lambda值:

const float labmda = (timeSincePrevious>0.2? 1: timeSincePrevious/0.2);

也就是说,当timeSincePrevious很小时,我们会使用一个小的lambda。

答案 2 :(得分:1)

过滤器建议可能没问题,但它无法解决问题:峰值将被平滑,但仍然存在。

如果您注销了触摸事件,那么这些峰值看起来就像是之前(0.001215毫秒)的时间差非常小的触摸,之前触摸的是大时间增量。

distance = 17.269917, timeDelta = 0.016132, speed = 1070.504639 
distance = 15.206906, timeDelta = 0.017494, speed = 869.251709 
distance = 15.882380, timeDelta = 0.017583, speed = 903.297546 
distance = 14.983324, timeDelta = 0.030101, speed = 497.771088      //low peak
distance = 15.435349, timeDelta = 0.001215, speed = 12703.991211    //high peak!
distance = 15.882380, timeDelta = 0.017343, speed = 915.795898 
distance = 15.890248, timeDelta = 0.016302, speed = 974.742249 
distance = 16.560495, timeDelta = 0.016468, speed = 1005.606445 
distance = 16.101242, timeDelta = 0.017291, speed = 931.201050 

我所做的是计算最近触摸事件之间的平均时间差值,如果触摸异常时间差值(±30%),我会忽略其速度(保持前一事件的速度)