简体   繁体   中英

Prevent vertical scroll on swipe -vanilla JS

I wrote this code to add swipe function for an image slider. The slider is working correctly.

However when i perform a right or left swipe there is some vertical scrolling which is distracting and annoying.

I'm storing the reference to touchstart in the touch object.

And on touchend event, if vertical distance (lenY) is more than 50, i trigger preventDefault on the touchstart.

This isn't working.

Simplest option is to call preventDefault directly on touchStart. But the image slider occupies a large part of the mobile screen making scrolling down the page tricky.

I need to pass the lenY (vertical distance) to the touch start handler to prevent default action.

function triggerTouch() {
    "use strict";
    var tZone = document.getElementById('sl-m'),
        touch = {},
        startX = 0,
        startY = 0,
        endX = 0,
        endY = 0;

    if (tZone) {
        tZone.addEventListener('touchstart', function (e) {
            startX = e.changedTouches[0].screenX;
            startY = e.changedTouches[0].screenY;

            // store reference to touch event
            touch.start = e;
        }, false);

        tZone.addEventListener('touchend', function (e) {
           endX = e.changedTouches[0].screenX;
           endY = e.changedTouches[0].screenY;

           var lenX = Math.abs(endX - startX);
           var lenY = Math.abs(endY - startY);

           // check if user intended to scroll down
           if (lenY < 50 && lenX > 50) {
                touch.start.preventDefault();
                e.preventDefault();
                swipe(tZone, startX, endX);
           }
        }, false);
    }
}

Since i haven't got an answer i am posting my own answer, hoping someone can provide the correct implementation.

I ended up using the css overflow property to temporarily disable vertical scroll.

This works perfectly though there is a small side effect. Once you swipe through the image slider, the scroll is disabled.

A swipe upwards is required to restore scroll to the page. Its not noticeable but i still want to figure the right way.

var touch = {};

window.onload = function () {
    "use strict";
    document.body.addEventListener("touchstart", touchHandler);
    document.body.addEventListener("touchend", touchHandler);
};

function touchHandler(e) {
    "use strict";

    var el = e.target;

    if (el.parentNode.id === "sl-m") {
        if (e.type === "touchstart") {
            touch.startX = e.changedTouches[0].screenX;
            touch.startY = e.changedTouches[0].screenY;
        } else {
            touch.endX = e.changedTouches[0].screenX;
            touch.endY = e.changedTouches[0].screenY;

            touch.lenX = Math.abs(touch.endX - touch.startX);
            touch.lenY = Math.abs(touch.endY - touch.startY);

            if (touch.lenY < 20) {
                // disable scroll
                document.body.style.overflowY = "hidden";

                // do swipe related stuff
                swipe(el.parentNode);
            } else {
                // enable scroll if swipe was not intended
                document.body.style.overflowY = "scroll";
            }
        }
    } else {
        // keep scroll enabled if touch is outside the image slider 
        document.body.style.overflowY = "scroll";
    }
}
html,
body {
     overflow: hidden;
}

Did you try this?

I want to share the solution that works for me. The above solution did not work on ios. I am sorry for my English. I do not know english.

function stop(e){
e=e || event;
e.preventDefault;
}
window.onscroll=stop(); //-->Yes, we will use it ..

For example, where you will use;

function move(event){

var finish=event.touches[0].clientX;
var verticalFinish=event.touches[0].clientY;
var diff=finish-strt;
var verticalDiff=verticalStrt-verticalFinish;
var f;

if(diff<0 && (Math.abs(diff)>Math.abs(verticalDiff)/3)){
    f=verticalDiff+widthOffset;
slayt[x].style.left=diff+"px";
slayt[x].style.transition="none";
slayt[y].style.left=f+"px";
slayt[y].style.transition="none";

  window.onscroll=stop(); //-->we used it here :)

  } 

else if(diff>0 && (Math.abs(diff)>Math.abs(verticalDiff)/3)){
    f=diff-widthOffset;
slayt[x].style.left=diff+"px";
slayt[x].style.transition="none";
slayt[z].style.left=f+"px";
slayt[z].style.transition="none";

  window.onscroll=stop();//-->we used it here :)

    }
 }

but there is a small problem. cancels if there is another function related to scrolling. return true; it does not work. I also write twice if I have a function related to the slider inside and outside the touchend.

function end(event){
//"touchend" related codes...
//bla bla
window.onscroll=function(){m=window.pageYOffset;console.log(m);if(m>=850) 
{buton.style.display="block";}else{buton.style.display="none";}}
}

If it is useful, I will be happy...

Update : I typed wrong. I want to fix. Actually, the scroll event cannot be canceled unfortunately. So the event we canceled above, scroll is not a vertical scroll event. All events.

window.onscroll=stop(); // ==>improper use
stop(); // ==> actually - Correct usage

It just needs to be written so stop().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM