skip to Main Content

I’m working on a site that overflows horizontally on desktop, as opposed to the usual vertical scroll. This all works fine, however in order to improve the user experience, I have to modify the scrolled amount in order to move larger sections of the screen a time. The problem with the code I’m using is that it doesn’t provide a very smooth experience: The movement seems to be quite clunky.

This is the snippet I’m using and it’s executed on the mousewheel event:

function scrollHorizontally(e) {
    e = window.event || e;
    var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
    document.documentElement.scrollLeft -= (delta*60); // Multiplied by 60
    document.body.scrollLeft -= (delta*60); // Multiplied by 60
    e.preventDefault();
}

As you can see, I have to modify the delta * 60 in order to move the scroll bars an adequate amount.

I’d like to know if it’s possible to make this a smooth transition rather than (what seems to be) chunking the user across a fixed pixel amount at a time.

I’ve tried using scrollBy({ left: <amount>, behavior: 'smooth' }); but this doesn’t seem to provide a good user experience: it just seems to ease the movement a little but it feels laggy and inconsistent.

What I’d like is for the user to smoothly animate the desired amount. Does anyone know if this is possible?

I’ve actually built this within a Vue 3 application so would be interested if Vue has any ways to handle this? I’m happy to use native js though.

Thanks

2

Answers


  1. you can try this way.

    <template>
     <div v-scrollHorizontally="scrollHorizontally"></div>
    </template>
    <script>
    export default {
     method: {
      scrollHorizontally(e) {
       e = window.event || e;
       var delta = Math.max(-1, Math.min(1, (e.wheelDelta || - e.detail)));
       var scrollAmount = delta * 60;
       window.scrollBy({ left: scrollAmount, behavior: 'smooth'});
       e.preventDefault();
      }
     }
    }
    </script>
    
    Login or Signup to reply.
  2. Let’s try canceling the scroll event and implementing our own physics using animation. I removed the scrollbars to hide the fact that scrolling using the scrollbar wouldn’t work as expected in this simple example.

    var offsetX = 0
    var speedX = 0
    const deltaMultiplier = 10
    const maxSpeed = 160
    const friction = 0.85
    
    function scrollHorizontally(ev) {
      ev.preventDefault()
      var delta = -1 * Math.sign(ev.wheelDelta)
      speedX += delta * deltaMultiplier
      speedX = speedX > 0 ? Math.min(speedX, maxSpeed) : Math.max(speedX, -maxSpeed)
      return false;
    }
    
    function draw() {
      offsetX += speedX
    
      const element = document.documentElement
      const maxScrollLeft = element.scrollWidth - element.clientWidth
      offsetX = Math.min(offsetX, maxScrollLeft)
      offsetX = Math.max(offsetX, 0)
    
      element.scrollLeft = offsetX
      speedX *= friction
    
      // about 60 times a second
      requestAnimationFrame(draw)
    }
    
    // must be passive so will be cancelable
    addEventListener('mousewheel', scrollHorizontally, {
      passive: false
    })
    
    
    draw()
    .div {
      width: 2500px;
      height: 100px;
      background: linear-gradient(0.25turn, green, blue);
      white-space: nobreak;
    }
    
    body {
      overflow: hidden;
    }
    <div class="div">
      <h1>mouse wheel me</h1>
      function scrollHorizontally(e) { e = window.event || e; var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); console.log(delta) document.documentElement.scrollLeft -= (delta * 60); // Multiplied by 60 document.body.scrollLeft -= (delta
      * 60); // Multiplied by 60 e.preventDefault(); } addEventListener('mousewheel', scrollHorizontally)
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search