0

I am trying to recreate the Monocle ereader. As best I understand, it works by columnating the page and then scrolling horizontally across the columns.

I have the following HTML and Javascript:

body {
  column-width: 100vw;
  max-height: calc(100vh - 30px);
  box-sizing: border-box;
}

window.addEventListener(
  'wheel',
  (evt) => {
    const delta = evt.deltaX + evt.deltaY
    const pages = Math.round(Math.abs(delta) / delta)
    const curr = Math.round(window.scrollX / window.innerWidth)
    window.scroll((curr + pages) * window.innerWidth, 0)
  }
)

As this pen shows when you scroll, as the pages progress, the text drifts to the left.

dysbulic
  • 3,005
  • 2
  • 28
  • 48
  • I don't see the problem with your pen. It seems like it's working as intended, i.e. it is scrolling horizontally one *page* at a time. – Richard Feb 08 '20 at 08:07
  • Based on an answer below I changed it so this example works. The original has content inside an iframe that is centered in the page and, somewhere, things get misaligned. I'm working on getting the pen to show the error or get the actual buggy code online. – dysbulic Feb 08 '20 at 08:20
  • It turns out the bug only appears when the development tools are open on Chrome. – dysbulic Feb 23 '20 at 08:16

2 Answers2

1

It looks like it's drifting due to the vertical scrollbar on the right. For me, adding overflow-y: hidden; to the body's css to hide the scrollbar seemed to do the trick.

If you need to have the scrollbar there, you might need to calculate the scrollbar width and add/subtract it to compensate. More info on doing that here: https://stackoverflow.com/a/13382873/6184972

Steve
  • 10,435
  • 15
  • 21
  • You're right. That's not the problem with my original code which doesn't have the vertical scroll. I'm going to have to refactor the example some… – dysbulic Feb 08 '20 at 06:27
0

Poor browser has to repaint for every instance of a 'wheel' event! Try console logging for each wheel event, you'll see it's pretty frequent! Try reducing the number of times the browser has to repaint. It'll be a balancing act between a smooth scroll and a better performance:

let counter = 0;
const buffer = 3;  // I made this a variable so you can easily see what it is and change it
window.addEventListener(
  'wheel',
  (evt) => {
    const delta = evt.deltaX + evt.deltaY
    const pages = Math.round(Math.abs(delta) / delta)
    const curr = Math.round(window.scrollX / window.innerWidth)
    let scrollAmount = (curr + pages) * window.innerWidth
      if (scrollAmount >= (counter + buffer)) {
        window.scroll(scrollAmount, 0)
        counter = scrollAmount
      }
  }
)

Sydney Y
  • 2,912
  • 3
  • 9
  • 15