Pak Ho Cheung
Pak Ho Cheung

Reputation: 1426

window.scrollTo(x, y) is not working in mobile iOS

Trying to create a website that can

  1. move screen to the RIGHT while scrolling UP
  2. move screen to the LEFT while scrolling DOWN

I used the function of window.scrollTo for moving the screen. It works perfect in decktop browser and the desktop Chrome's mobile view. But, the function is not working in mobile even iOS Safari or iOS Chrome. Tried the setTimeout, but still not work. Any suggestions?

Below is the simplified codes that has the same issue.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<body style="margin: 0px; height: 100%; overflow: hidden;"> <!-- disable desktop scrolling -->
    <img style="width: 300%;" src="https://imaging.nikon.com/lineup/dslr/df/img/sample/img_01.jpg">
</body>

<script type="text/javascript">

    // Mobile
    document.body.addEventListener('touchmove', function(e){ 
        handleTouchMove(e);
        
        e.preventDefault(); // disable mobile user interaction
    }, { passive: false });

    var currentX = 0;

    function scrolling(isUp) {
        var movingBy = 10;
        // backward
        if (isUp) {
            currentX -= Math.min(movingBy, currentX);
        // forward
        } else {
            currentX += Math.min(movingBy, $(window).width() * 2 - currentX);
        }
        window.scrollTo(currentX, 0);
    }

    document.addEventListener('touchstart', handleTouchStart, false);  

    var xDown = null;                                                        
    var yDown = null;                                               
                                                                             
    function handleTouchStart(evt) {
        var touches = evt.touches || evt.originalEvent.touches;
        const firstTouch = touches[0];                                      
        xDown = firstTouch.clientX;                                      
        yDown = firstTouch.clientY;                                      
    };                                                
                                                                             
    function handleTouchMove(evt) {
        var xUp = evt.touches[0].clientX;                                    
        var yUp = evt.touches[0].clientY;

        var xDiff = xDown - xUp;
        var yDiff = yDown - yUp;
                                                                             
        if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {     
            // left and right            
        } else {
            // up and down
            scrolling(yDiff <= 0);                                                           
        }

        xDown = xUp;
        yDown = yUp;                                             
    };

    // desktop
    ...
</script>

Upvotes: 0

Views: 2254

Answers (3)

Mark Alvin
Mark Alvin

Reputation: 87

Any windows scroll function will not work in any IOS device when you are calling it inside an iframe element. But you can use parent.window.postMessage() and use any javascript windows scroll function available such as window.scroll(), window.scrollTo(), window.scrollBy().

Get your selected element object xy coordinates and pass it to parent.window.postMessage()

Upvotes: 0

Cody Pace
Cody Pace

Reputation: 178

It's your overflow. I removed overflow:hidden and tested it on an ios device and it worked fine. Just remove that line and you'll be good. May need to play with hiding just x or y overflow depending on what you're looking for.

EDIT: If you are wanting to prevent default scrolling and only allow scrolling from js you might look at this post -> Overflow-x:hidden doesn't prevent content from overflowing in mobile browsers

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<body style="margin: 0px; height: 100%;"> <!-- disable desktop scrolling -->
    <img style="width: 300%;" src="https://imaging.nikon.com/lineup/dslr/df/img/sample/img_01.jpg">
</body>

<script type="text/javascript">

    // Mobile
    document.body.addEventListener('touchmove', function(e){ 
        e.preventDefault(); // disable mobile user interaction
        handleTouchMove(e);
        
        
    }, { passive: false });

    var currentX = 0;

    function scrolling(isUp) {
        var movingBy = 10;
        // backward
        if (isUp) {
            currentX -= Math.min(movingBy, currentX);
        // forward
        } else {
            currentX += Math.min(movingBy, $(window).width() * 2 - currentX);
        }

        window.scrollTo(currentX, 0);
    }

    document.addEventListener('touchstart', handleTouchStart, false);  

    var xDown = null;                                                        
    var yDown = null;                                               
                                                                             
    function handleTouchStart(evt) {
        var touches = evt.touches || evt.originalEvent.touches;
        const firstTouch = touches[0];                                      
        xDown = firstTouch.clientX;                                      
        yDown = firstTouch.clientY;      
    };                                                
                                                                             
    function handleTouchMove(evt) {
        var xUp = evt.touches[0].clientX;                                    
        var yUp = evt.touches[0].clientY;

        var xDiff = xDown - xUp;
        var yDiff = yDown - yUp;
                                                                             
        if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {     
            // left and right            
        } else {
            // up and down
            scrolling(yDiff <= 0);                                                           
        }

        xDown = xUp;
        yDown = yUp;                                             
    };
</script>

Upvotes: 0

sungryeol
sungryeol

Reputation: 4015

possible solution

although it is not certain if this is the real reason, code in the question is missing a following part that is necessary for iOS screen size calculation.

<meta name="viewport" content="width=device-width; initial-scale=1.0;">

related SO answer: $(window).width() returning same value in portrait/landscape mode of iPhone

Upvotes: 0

Related Questions