如何在Mac Safari中检测/禁用惯性滚动?

时间:2010-12-02 19:51:52

标签: javascript macos

有没有办法禁用或检测来自Mac上“惯性”设置的车轮事件?

我希望能够区分真实事件和其他事件......或者禁用特定页面的那种滚动。

7 个答案:

答案 0 :(得分:4)

是和否。

您可以使用触地得分/向上,并滚动为事件以查找正在移动的页面,但如果操作系统正在进行惯性滚动,则不会触发这些事件。好玩,对吧?

然而,您可以不断检测的一件事是window.pageYOffset。当惯性滚动发生时,该值将不断变化但不会抛出事件。所以你可以拿出一组定时器来继续检查惯性滚动并继续运行直到页面停止移动。

棘手的东西,但它应该有用。

答案 1 :(得分:3)

哦这个问题怎么杀了我:/

我正在创建“无尽”滚动大文件查看器。

更糟糕的是,这个编辑器嵌入在有自己滚动条的页面中,因为它比一个屏幕更大。

U使用overflow-x滚动进行水平滚动,但是对于垂直滚动,我需要当前行的荧光笔(如大多数现代IDE中所见),所以我使用jquery mousewheel插件,并向上或向下滚动移动内容以获得行高。

它在ubuntu / chrome上完美运行,但有时在MacOS Lion / Chrome上运行,有时候, 当你滚动时,它不会阻止编辑器元素上的默认滚动,并且事件传播“向上”并且页面自动开始滚动。

我甚至无法描述这有多烦人。

至于惯性滚动它,我用两个定时器成功减少它

var self = this;
// mouse wheel events
    $('#editorWrapper').mousewheel(function (event, delta, deltax, deltay) {

        self._thisScroll = new Date().getTime();


        //
        //this is entirely because of Inertial scrolling feature on mac os :(
        //
        if((self._thisScroll - self._lastScroll) > 5){
            //
            //
            // NOW i do actual moving of content
            //
            //

            self._lastScroll = new Date().getTime(); 
        }

5ms是我发现在我的MacBook Pro上最自然的感觉,你必须快速滚动鼠标滚轮来抓住其中一个......

即使如此,有时在Mac上的Mac侦听器上的侦听器也不会阻止默认,并且页面向下滚动。

答案 2 :(得分:2)

嗯,(我可能错了),我认为Mac上的“惯性”设置都是由系统本身,浏览器或任何程序计算的,只是认为用户正在快速滚动,而不是放慢速度。

答案 3 :(得分:2)

我不确定其他浏览器,但在我的Chrome,FF,Safari(mac)惯性滚动期间会触发以下事件:

var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel";
function scrollEE (e) {
    console.log(e);
}
window.addEventListener(mousewheelevt, scrollEE, false);

答案 4 :(得分:2)

有一个库可以解决这个问题。

https://github.com/d4nyll/lethargy

安装后,请使用它:

var lethargy = new Lethargy();

$(window).bind('mousewheel DOMMouseScroll wheel MozMousePixelScroll', function(e){
  if(lethargy.check(e) === false) {
    console.log('stopping zoom event from inertia')
    e.preventDefault()
    e.stopPropagation();
  }
  console.log('Continue with zoom event from intent')
});

答案 5 :(得分:1)

在滚动完成后,基于滚动位置的动画对象出现了很大的问题,而惯性滚动实际上让我感到烦恼。我最终计算了速度,以确定惯性滚动将持续多长时间并使用它在动画制作之前等待。

var currentY = 0;
var previousY = 0;
var lastKnownVelocity = 0;
var velocityRating = 1;
function calculateVelocity() {
    previousY = currentY;
    currentY = $('#content').scrollTop();
    lastKnownVelocity = previousY - currentY;
    if (lastKnownVelocity > 20 || lastKnownVelocity < -20) {
        velocityRating = 5;
    } else {
        velocityRating = 1;
    }
}

$('#content').scroll(function () {
    // get velocity while scrolling...
    calculateVelocity();
    // wait until finished scrolling...
    clearTimeout($.data(this, 'scrollTimer'));
    $.data(this, 'scrollTimer', setTimeout(function() {
        // do your animation
        $('#content').animate({scrollTop: snapPoint}, 300);
    }, 300*velocityRating)); // short or long duration...
});

答案 6 :(得分:1)

我找到了一个非常适用于此的解决方案。下面是我项目中的一些粘贴代码。它基本上归结为这个逻辑:

当任何一个条件成立时,滚动事件来自人类:

  • 方向是与最后一个方向相反的方向
  • 自上次滚动事件(选择100毫秒以确定)后超过50毫秒
  • delta值至少与前一个值一样高

由于Mac spams在启用惯性滚动时每隔20ms向浏览器滚动事件滚动事件,这是一种非常安全的方式。我至少没有失败过。只检查自上次滚动以来的时间不会起作用,因为如果&#34;虚拟飞轮&#34;那么用户将无法再次滚动。即使他们没有滚动3秒钟,它仍然在运行。

this.minScrollWheelInterval = 100; // minimum milliseconds between scrolls
this.animSpeed = 300;

this.lastScrollWheelTimestamp = 0;
this.lastScrollWheelDelta = 0;
this.animating = false;

document.addEventListener('wheel',
    (e) => {

        const now = Date.now();

        const rapidSuccession = now - this.lastScrollWheelTimestamp < this.minScrollWheelInterval;
        const otherDirection = (this.lastScrollWheelDelta > 0) !== (e.deltaY > 0);
        const speedDecrease = Math.abs(e.deltaY) < Math.abs(this.lastScrollWheelDelta);

        const isHuman = otherDirection || !rapidSuccession || !speedDecrease;

        if (isHuman && !this.animating) {
            this.animating = true; // current animation starting: future animations blocked
            $('.something').stop().animate( // perform some animation like moving to the next/previous page
                {property: value},
                this.animSpeed,
                () => {this.animating = false} // animation finished: ready for next animation
            )
        }

        this.lastScrollWheelTimestamp = now;
        this.lastScrollWheelDelta = e.deltaY;

    },
    {passive: true}
);

顺便说一下,有一点需要注意:Mac在滚动时也有加速,即:首先,每个连续事件的delta值更高。看起来这不会持续超过100毫秒左右。因此,如果由于滚动事件而触发的任何动作/动画持续至少100毫秒并在此期间阻止所有其他动作/动画,这绝不是问题