Home > Mobile >  Need a JS function that does something every 1000px scrolled
Need a JS function that does something every 1000px scrolled

Time:12-29

Basically I need a function, or to better say it, a window event listener that performs an action every 1000px scrolled (both from up to down and from down to up). Every answer suggested that I used a module like so:

 if (window.scrollY % 1000 == 0) {//do something} 

but it doesn't work because window.scrollY doesn't return every single pixel, it might return let's say 5000, so 500000 is actually 0, but another time it might return a number around 5000, like 5123 which wouldn't return 0 from the module operator. This is my JS function as of now:

window.addEventListener("scroll", e => {

        scrollpos = window.scrollY;
        // console.log(scrollDown);
        console.log("\n pos: "   scrollpos);


        if (scrollpos % 1000 == 0) {

            // if (imgIndex < totImg - 1) {
            //     imgIndex  ;
            // } else {
            //     imgIndex = 0;
            // }

            // imgArr[imgIndex   1].style.opacity = "0";
            // imgArr[imgIndex].style.opacity = "1";
            console.log("\n\n\nworked on: "   scrollpos "\n\n\n");

        }


    });

I added some console logs where you can clearly see that the window.scrollY doesn't return every single pixel, and that's why the if as it is doesn't log the message every 1000px

CodePudding user response:

I'm going to provide an answer, although I'm not 100% sure that I understood the problem correctly.

From what I understand, the particular issue is that your modulo operation would be true only for 0, 1000, 2000, 3000, and so on. This could be fixed quite easily, using a state variable (prevScroll) and integer division (Math.floor(window.scrollY / threshold)):

let prevScroll = 0
const threshold = 1000

window.addEventListener("scroll", () => {
    const currScroll = Math.floor(window.scrollY / threshold)

    if (currScroll !== prevScroll) {
        prevScroll = currScroll

        // Your code
    }
})

You could use this code instead if you want to start from a certain position:

let prevScroll = 0
const threshold = 1000
const startFrom = 1200 // This could be any positive integer you want

window.addEventListener("scroll", () => {
    if(window.scrollY < startFrom) {
        return
    }

    const currScroll = Math.floor(window.scrollY / threshold)

    if (currScroll !== prevScroll) {
        prevScroll = currScroll

        // Your code
    }
})

CodePudding user response:

You can keep track of the last position and each time the scroll event triggers, add the delta into a buffer. When such buffer will be over a given threshold (1000) it will trigger another action and the buffer will be reset.

https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY

The read-only scrollY property of the Window interface returns the number of pixels that the document is currently scrolled vertically.

So that's not enough to determine how much space was traveled since the latest scroll in the past. But if we store each time the latest retrieved value, only after we already used that value to calculate the distance between the previous position and the current one, we can each time cumulate the distance scrolled so far.

When such cumulated distance is over 1000, we reset the distance buffer and the counting loops again.

Worth saying that we used the Math.abs above the difference between the current and previous positions, because the distance is a positive value anyway.

let lastPos = 0;
let buffer = 0;
window.addEventListener("scroll", e => {
  const scrollpos = window.scrollY;
  buffer  = Math.abs(scrollpos - lastPos);
  lastPos = scrollpos;
  if (buffer >= 1000) {
    buffer = 0;
    console.log(`worked on: ${scrollpos}`);
  }
  logNumber(buffer.toFixed(2));
});

function logNumber(value){
  document.getElementById('buffer').innerText = value;
}
body{
  font-size: 20px;
}

.page{
  height: 1000cm;
  border: solid;
  padding: 1em;
}

.topnav{
  position: sticky;
  top: 0;
  text-align: right;
  padding: 3em 6em;
}

#buffer{
  border: solid 4px gray;
  padding: .5em;
  font-size: 40px;
  font-weight: 600;
  font-family: sans-serif;
}
<div >
  <span id="buffer">0</span>
</div>
<div >Page content...</div>

  • Related