Javascript 在移动设备上对抗触摸事件,highjacking正常滚动

Javascript 在移动设备上对抗触摸事件,highjacking正常滚动,javascript,mobile,scroll,touch,touch-event,Javascript,Mobile,Scroll,Touch,Touch Event,我对代码进行了多次检查,但我无法找到它在基于触摸的设备上失败的原因: /** * Initialize touch event listener. * * @returns {Plugin} */ touch: function () { var self = this; this._$body.bind('touchstart', function (event) { var st

我对代码进行了多次检查,但我无法找到它在基于触摸的设备上失败的原因:

    /**
     * Initialize touch event listener.
     *
     * @returns {Plugin}
     */
    touch: function () {
        var self = this;

        this._$body.bind('touchstart', function (event) {
            var startEvent = event.originalEvent.touches[0];

            event.preventDefault();
            self._$body.bind('touchmove', function (event) {
                var moveEvent = event.originalEvent.touches[0];
                var diff = { x: startEvent.clientX - moveEvent.clientX, y: startEvent.clientY - moveEvent.clientY };
                var nextStep;
                event.preventDefault();
                if ((diff.y <= -100 || diff.y >= 100) && Math.abs(diff.y) > Math.abs(diff.x)) {
                    nextStep = diff.y < 0 ? self._currentStep - 1 : self._currentStep + 1;
                    self.customScrollTo(nextStep);
                }
                return false;
            });

            return false;
        });

        return this;
    },
/**
*初始化触摸事件侦听器。
*
*@returns{Plugin}
*/
触摸:功能(){
var self=这个;
此.$body.bind('touchstart',函数(事件){
var startEvent=event.originalEvent.touchs[0];
event.preventDefault();
self.\u$body.bind('touchmove',函数(事件){
var moveEvent=event.originalEvent.touchs[0];
var diff={x:startEvent.clientX-moveEvent.clientX,y:startEvent.clientY-moveEvent.clientY};
var-nextStep;
event.preventDefault();
如果((差异y=100)和数学abs(差异y)>数学abs(差异x)){
下一步=差异y<0?自。\电流步骤-1:自。\电流步骤+1;
self.customScrollTo(下一步);
}
返回false;
});
返回false;
});
归还这个;
},
演示(自签名ssl,不用担心!):

问题:当触摸被激活时,滚动条会直接跳到底部

预期结果:一触式交互等于1个滚动部分


有什么想法吗?

我认为touchmove事件触发了多次,请尝试使用touchend

关于: 我已经用google chrome live javascript edit测试了你的代码。 它在touchmove事件中进行了以下修改

setTimeout(function(){ self.customScrollTo(nextStep); }, 250);

我也认为
touchmove
事件的回调会在每次触摸移动时触发。通过从该功能返回
false
,您只能取消该单触移动事件,而不是所有后续触移动事件

您不能使用
touchend
事件,因为您要调用
self.customScrollTo(下一步)指针移动100像素后

要防止在指针移动100 px后执行
touchmove
回调,可以通过多种方式执行,例如

  • 使用标志变量,如
    var trackPointer=true,检查此标志
    每次触发
    touchmove
    时,将此标志设置为
    false
    指针已移动100像素
  • 当指针移动100像素时, 将
    starteEvent
    设置为
    null
    ,并在上检查此变量
    触摸移动
  • 当指针移动时,取消绑定
    touchmove
    事件 旅行了100像素
  • 注意:每次在此元素上触发
    touchstart
    时,都会绑定
    touchmove
    事件,这些事件不会相互覆盖,而是叠加在一起!因此,您可能需要考虑仅对事件绑定一次(例如,在DOM准备就绪),或者在不再需要的时候取消绑定事件。 后者可能是最简单的,也可以在
    touchend
    上完成(使用名称空间只是为了确保不解除由其他脚本绑定的相同事件的绑定):

    当指针移动100像素时:

    self.customScrollTo(nextStep);
    // Unbind all touchmove.myNameSpace events.
    self._$body.unbind('touchmove.myNameSpace');
    
    由于当指针位于元素外部时不会触发“touchend”(我不确定
    touchmove
    ),因此您可能还希望在绑定之前解除绑定:

    event.preventDefault();
    // Unbind all touchmove.myNameSpace events and (re)bind touchmove.myNameSpace event.
    self._$body.unbind('touchmove.myNameSpace').bind('touchmove.myNameSpace', function (event) {
      var moveEvent = event.originalEvent.touches[0];
    
    因此,您可以尝试(我尚未测试):

    /**
    *初始化触摸事件侦听器。
    *
    *@returns{Plugin}
    */
    触摸:功能(){
    var self=这个;
    此.$body.bind('touchstart',函数(事件){
    var startEvent=event.originalEvent.touchs[0];
    event.preventDefault();
    self.$body.unbind('touchmove.myNameSpace').bind('touchmove.myNameSpace',函数(事件){
    var moveEvent=event.originalEvent.touchs[0];
    var diff={x:startEvent.clientX-moveEvent.clientX,y:startEvent.clientY-moveEvent.clientY};
    var-nextStep;
    event.preventDefault();//Math.abs(diff.x)){
    下一步=差异y<0?自。\电流步骤-1:自。\电流步骤+1;
    self.customScrollTo(下一步);
    //解除所有touchmove.myNameSpace事件的绑定。
    self.$body.unbind('touchmove.myNameSpace');
    }
    返回false;
    });
    返回false;
    });
    //解除touchend.myNameSpace上所有touchmove.myNameSpace事件的绑定。
    self.$body.bind('touchend.myNameSpace')。函数(事件){
    self.$body.unbind('touchmove.myNameSpace');
    });
    归还这个;
    },
    

    PS:您可能需要使用类似HammerJS()的库,使手势在浏览器和非触摸设备上都能正常工作。

    首先,我建议您使用Modernizer来检测触摸

    if (Modernizr.touch) {
        $("body").swipe({
            //Generic swipe handler for all directions
            swipe: function (event, direction, distance, duration, fingerCount, fingerData) {
             if(distance >= 100) //Check the units in px or unit
             {
                if (direction === "up") {
                       self.customScrollTo(nextStep);
                } else if (direction === "down") {
                       self.customScrollTo(prevStep);
                }
             }
           }
        });
    }
    
    我只是把逻辑放在上面。“自我”只是你的目标

    要使滑动事件正常工作,您必须包含jquery插件

    因此,当触发“self.customScrollTo(nextStep)”事件时,“starteEvent”值是新值,即接触点的当前位置。因此,当再次调用touchmove事件时。它将再次获得一组新的值进行计算。
    请检查此代码并告诉我此代码是否有效。即使它不正确。

    Scroll根本不工作,因为meNormal Scroll在Chrome中不工作,touch在mobile中不工作safari@salivan给我点时间,我会想办法的。顺便说一句,如果你继续设定这么多的奖金,你的回购协议很快就会到期。)@SamBraslavskiy好吧,这些问题很难回答,所以我不认为让它们成为普通的问题对你们来说是不公平的。。。我正在为这些情况积累REP:)不知何故,这些.jpg和.svg中的很多都没有为我加载。不过,我不知道这是否只是我的问题。嗅探触摸是不可靠的,因为现在的设备可以同时支持鼠标和触摸(Chromebook和许多W8 PC),而且一些设备确实支持触摸,但没有连接触摸设备,因此重新启动
    /**
     * Initialize touch event listener.
     *
     * @returns {Plugin}
     */
    touch: function () {
        var self = this;
    
        this._$body.bind('touchstart', function (event) {
            var startEvent = event.originalEvent.touches[0];
    
            event.preventDefault();
            self._$body.unbind('touchmove.myNameSpace').bind('touchmove.myNameSpace', function (event) {
                var moveEvent = event.originalEvent.touches[0];
                var diff = { x: startEvent.clientX - moveEvent.clientX, y: startEvent.clientY - moveEvent.clientY };
                var nextStep;
                event.preventDefault(); // <- Not necessary since you completely cancel the event by returning false.
                if ((diff.y <= -100 || diff.y >= 100) && Math.abs(diff.y) > Math.abs(diff.x)) {
                    nextStep = diff.y < 0 ? self._currentStep - 1 : self._currentStep + 1;
                    self.customScrollTo(nextStep);
    
                    // Unbind all touchmove.myNameSpace events.
                    self._$body.unbind('touchmove.myNameSpace');
                }
                return false;
            });
    
            return false;
        });
    
        // Unbind all touchmove.myNameSpace events on touchend.myNameSpace.
        self._$body.bind('touchend.myNameSpace').function (event) {
            self._$body.unbind('touchmove.myNameSpace');
        });
    
        return this;
    },
    
    if (Modernizr.touch) {
        $("body").swipe({
            //Generic swipe handler for all directions
            swipe: function (event, direction, distance, duration, fingerCount, fingerData) {
             if(distance >= 100) //Check the units in px or unit
             {
                if (direction === "up") {
                       self.customScrollTo(nextStep);
                } else if (direction === "down") {
                       self.customScrollTo(prevStep);
                }
             }
           }
        });
    }
    
    /**
     * Initialize touch event listener.
     *
     * @returns {Plugin}
     */
    
    touch: function () {
        var self = this;
        var flag = false;
        this._$body.bind('touchstart', function (event) {
            var startEvent = event.originalEvent.touches[0];
    
    
            self._$body.bind('touchmove', function (event) {
                var moveEvent = event.originalEvent.touches[0];
                var diff = { x: startEvent.clientX - moveEvent.clientX, y: startEvent.clientY - moveEvent.clientY };
                var nextStep;
    
                if (((diff.y <= -100 || diff.y >= 100) && Math.abs(diff.y) > Math.abs(diff.x)) && flag == true) {
    
                    nextStep = diff.y < 0 ? self._currentStep - 1 : self._currentStep + 1;
                    self.customScrollTo(nextStep);
                    startEvent = event.originalEvent.touches[0];  // Just added this line here.
                }
                event.preventDefault();
    
                return false;
            });
    
            return false;
        });
    
        return this;
    },
    
      startEvent = event.originalEvent.touches[0];