scroll-js icon indicating copy to clipboard operation
scroll-js copied to clipboard

Add horizontal scroll support

Open markcellus opened this issue 10 years ago • 9 comments

Vertical scroll is nice but what about horizontal scroll?

markcellus avatar Jan 30 '15 18:01 markcellus

@mkay581 isn't the first param the X scroll?

jvgomg avatar Jan 04 '16 12:01 jvgomg

~The first param to Scrolls .to() method is x, which is the horizontal scroll on the x axis, yes. But its not currently being used. I made the decision to include it so that future horizontal support will be easy.~ the API has since been changed. See updated README.

markcellus avatar Jan 04 '16 14:01 markcellus

Is horizontal scroll still not supported?

svensson-david avatar Mar 20 '19 09:03 svensson-david

No it isn't unfortunately. 😞 Just haven't had time to get to it. But do a lot of people need this? Horizontal scrolling seems rare when compared to vertical scrolling and haven't really seen this ticket gain as much popularity. I am open to accepting PRs though if you think its something you can tackle.

markcellus avatar Mar 22 '19 12:03 markcellus

No worries! Needed it for a Netflix type navigation with a lot of titles being shown horizontally. Trying to get it working with the the browser native scrolling behavior: smooth for now but I'll revisit this if we cannot get it to work reliably.

We're already using this library for some other scrolling and it's been really great this far 😃 Thanks!

svensson-david avatar Mar 22 '19 13:03 svensson-david

I've hacked together some changes for scrollTo to accept x and y scrolling. This just works for the scrollTo function, it can be translated to the other methods but would require a bit more consideration to update all methods etc.

async function scrollTo(el = window, options = {}) {
  const scroll = ({
    from,
    to,
    startTime,
    duration = 400,
    easeFunc,
    resolve,
  }) => {
    window.requestAnimationFrame(() => {
      const currentTime = Date.now();
      const time = Math.min(1, (currentTime - startTime) / duration);

      if (from.top === to.top && from.left === to.left) {
        return resolve ? resolve() : null;
      }

      setScrollPosition(el, {
        top: easeFunc(time) * (to.top - from.top) + from.top,
        left: easeFunc(time) * (to.left - from.left) + from.left,
      });

      /* prevent scrolling, if already there, or at end */
      if (time < 1) {
        scroll({ from, to, startTime, duration, easeFunc, resolve });
      } else if (resolve) {
        resolve();
      }
    });
  };

  const currentScrollPosition = getScrollPosition(el);

  return new Promise(resolve => {
    scroll({
      from: currentScrollPosition,
      to: { top: options.top, left: options.left },
      startTime: Date.now(),
      duration: options.duration,
      easeFunc: t => {
        return t * (2 - t);
      },
      resolve,
    });
  });
}

function getScrollPosition(el) {
  if (
    el === document.body ||
    el === document.documentElement ||
    el instanceof Window
  ) {
    return {
      top: document.body.scrollTop || document.documentElement.scrollTop,
      left: document.body.scrollLeft || document.documentElement.scrollLeft,
    };
  } else {
    return {
      top: el.scrollTop || el.scrollTop,
      left: el.scrollLeft || el.scrollLeft,
    };
  }
}

function setScrollPosition(el, { top, left }) {
  if (
    el === document.body ||
    el === document.documentElement ||
    el instanceof Window
  ) {
    document.body.scrollTop = top;
    document.documentElement.scrollTop = top;

    document.body.scrollLeft = left;
    document.documentElement.scrollLeft = left;
  } else {
    el.scrollTop = top;
    el.scrollLeft = left;
  }
}

omonk avatar Aug 04 '20 08:08 omonk

Awesome @omonk! You mind submitting a PR? So I can better evaluate, run tests, etc?

markcellus avatar Aug 05 '20 12:08 markcellus

I can have a look at some point! I hacked this together quickly for a small personal project I'm working on but would be happy to contribute for others to use also

omonk avatar Aug 05 '20 12:08 omonk

Would also be excited to see this added ☝🏼 @markcellus @omonk

brandonmcconnell avatar Jul 20 '22 15:07 brandonmcconnell