我正在尝试检测触摸移动的速度,但我并不总能得到我期望的结果。 (补充说:速度激增太多了) 如果我正在做一些时髦的事情或提出更好的做法,有人能发现吗?
- (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);
}
答案 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%),我会忽略其速度(保持前一事件的速度)