如何使用touchstart和touchend手势获取滚动的当前位置

mcc*_*n19 5 javascript webkit mobile-safari ios

好的,我会尝试尽可能地解释我想要做的事情.

使用Webkit溢出滚动我创建了一个具有可堆叠标题的列表,就像iPhone联系人应用程序提供的效果一样.例如,'A'保持在顶部,直到'B'将其移开.等等.这在桌面上或用户仍在滚动时相对容易.

然而,一旦用户轻弹滚动器,它就会以缓慢减速的方式自动滚动,在此期间不会发出任何事件,直到滚动器完全停止,此时为时已晚.

经过大量研究后,我发现轻弹减速持续时间总是相同的(大约2.4秒),只是结束位置发生变化.我还可以看到很多人通过创建自己的库来模仿iOS行为来解决这个问题,这可能是我唯一的选择.

我正在尝试通过获取以下内容来自动滚动元素的滚动顶部:

  • 触摸开始位置
  • 触摸结束位置
  • 这两个手势之间的时差

这应该允许我在发生之前跟踪位置和最终结果.但是,我对如何正确使用此信息以获得所需结果感到困惑.任何信息或指针都会非常有用.


编辑

在遇到物理问题之后,我在Physics stackexchange上询问并收到了这个答案

因此,我相信这段代码应该有用.我想检查以确保我应用正确的逻辑

var timeStart = new Date().getTime(); //Triggered on a touchstart event 
var timeEnd = new Date.getTime(); //Triggered on a touchend event 
var startY = event.originalEvent.targetTouches.pageY //Pulled in from different functions containing the events 
var endY = event.originalEvent.changeTouches[0].pageY //The where the touch starts and ends in px 
var timeElasped = timeEnd - timeStart; 
var distance = startY - endY; 
var velocity = distance/timeElasped; 
var result = velocity * (timeElasped - (1/4.8)*(timeElasped*timeElasped))
Run Code Online (Sandbox Code Playgroud)

因此,结果应该与触发最终滚动事件时scrollTop生成的内容相同.


编辑2

可悲的是似乎没有用.因此,我不能给出正确信息的公式.

不知道我的位置是否正在上升或者我如何执行公式.


编辑3

我认为卷轴速度确实每隔325毫秒减少0.95倍.我从这篇有用的文章中找到了这些信息.

这一观察让我相信动量滚动是一种指数衰减.它的特点是腐烂的速度.表达它有两种不同的方式:半衰期(记得放射性衰变?)或时间常数.对于后者,它与一阶系统的阶跃响应非常相关.换句话说,减速系统只是一个过阻尼的弹簧质量系统.事实证明,一切仍然基于物理学.

amplitude = initialVelocity * scaleFactor;
step = 0;

ticker = setInterval(function() {
    var delta = amplitude / timeConstant;
    position += delta;
    amplitude -= delta;
    step += 1;
    if (step > 6 * timeConstant) {
        clearInterval(ticker);
    }
}, updateInterval);
Run Code Online (Sandbox Code Playgroud)

实际上,这就是Apple自己的PastryKit库(现在是iAd的一部分)中实现减速的方式.对于每个动画节拍(16.7毫秒,目标为60 fps),它将滚动速度降低0.95倍.这对应于325毫秒的时间常数.如果你是一个数学极客,那么显然你意识到滚动速度的指数性质将产生位置的指数衰减.通过一点点涂鸦,最终你会发现325是-16.7/ln(0.95).

这个Google Doc应该显示公式,希望我正确地做到了.左边是标准公式.在右边,我试图将速度降低0.95(速度*0.95).我已经从我的测试中添加了真实信息,以显示我遇到的问题.如果所有方程都是正确的并且以正确的逻辑方式完成,那么它必须是进入的数据.


编辑4

经过许多痛苦的时间后,我得出结论,这是针对safari mobile的webkit中的一个错误.最好的选择是使用JS库来模仿效果并等到修复bug.

  • 主要原因是停止所需的时间总是在变化,因此为了准确读数,过多的变量会发生变化.