0

I don't know if window.scrollTo has a duration in the option because it's all JSON and the API isn't clearly documented anywhere.

for (i = 0; i < 1000; i++) {
    var sine = Math.sin(i/10);
    var scroll = sine * 1000;
    console.log(scroll);
    window.scrollTo({top: scroll, left: 0, behavior: 'smooth' });
}

I'd like a page to scroll up and down continuously, but this doesn't seem to work. Instead of executing all of the instructions in order, like you think it would, it consoles all values, then does a scroll at the end.

There's also no sensible sleep function in JavaScript. Also, the duration of this scroll is totally arbitrary.

How should I try to do such a seemingly simple task in JavaScript?

I would think of doing something like this in pseudo-code:

i = 0;
while (true) {
    scroll = sine(i);
    scrollTo(sine);
    // if scrollTo is asynchronous or something.
    sleep(x); // x how ever long scroll takes.
    i += 1;
}

But there is no sleep function in JS, the execution isn't even in order, and I have no idea how long x takes.

EDIT:

Still no solution found.

https://codepen.io/waterwaltz/pen/gbOdQb/

This codepen demos a possible way with the following:

function loop() {
    $("html, body").animate({ scrollTop: "0" }, 1000).animate({scrollTop: "100"}, 1000, loop)
}

But there's no way to exit the loop! Because 1) JS global variables don't work at all and 2) passed variables also don't work (a callback with no parameters? Who wrote this language?)

The only example with a stoppable loop I can find is here:

https://codepen.io/gabrieleromanato/pen/jEfbn

But it uses CSS animations that don't scroll!

I love JavaScript!

EDIT 2:

It's even worse.

var thing = "GO";
window.setInterval(function() {
    console.log(thing);
    if (thing == "GO") {
        $("html, body").animate({ scrollTop: "0" },1000)
        $("html, body").animate({ scrollTop: "1000" },1000)
    }
});

Running this with thing initially set to "GO" will result in a scroll loop, and even consoles "GO", but then setting thing to "NO" (or something else), doesn't just not stop the loop, but consoles "NO" while keeping the loop going!

I'm now at a total loss.

Alexander Kleinhans
  • 5,950
  • 10
  • 55
  • 111
  • 1
    for loop is a blocking statement which means it will block the execution of the main thread until it's done, and as you might know `javascript` is a single threaded languages meaning it only runs in one thread one of which it shares with the DOM therefore all the scrolling you're doing inside the for loop won't happen until it's done that's why you only see the last one, try using `setInterval()` – Rainbow Apr 11 '19 at 19:06
  • 1
    You can use `setTimeout` to allow the UI to update. – Jay Buckman Apr 11 '19 at 19:08
  • 1
    @ZohirSalak or promise and await. Also javascript does not have a valid sleep function, but [you can do that on your own](https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep) – weegee Apr 11 '19 at 19:08
  • 1
    You shouldn't put down an entire language simply because you haven't yet figured out how to use it and all its capabilities. And if you want people to help you, ragging on the language that they may love is not going to be very productive. – cybersam Apr 11 '19 at 19:35
  • I'm not the first person to put down this language. And I won't be the last. – Alexander Kleinhans Apr 11 '19 at 19:43

2 Answers2

0

Here you have an example. This is one way to do it.

Though one could also continually execute the rAF function via requestAnimationFrame and then check the time passed as a parameter to rAF (a DOMHighResTimestamp).

var i = 0;

function doSinScroll(num) {
  var sine = Math.sin(num / 10);
  var scroll = sine * 1000;
  console.log(scroll);
  window.scrollTo({
    top: scroll,
    left: 0,
  });
}

function rAF() {
  doSinScroll(i++);
  if (i < 1000) {
    setTimeout(function() {
      window.requestAnimationFrame(rAF);
    }, 100);
  }
}

window.requestAnimationFrame(rAF);
.red,
.white {
  width: 100%;
  height: 128px;
}

.red {
  background-color: red;
}

.white {
  background-color: white;
}
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
<div class="red">&nbsp;</div>
<div class="white">&nbsp;</div>
Wieger
  • 663
  • 1
  • 9
  • 24
0

Ok, here's the solution in the special "JavaScript way" using setInterval.

var do_scroll = "NO";

window.setInterval(function() {
    if (do_scroll == "GO") {
        $("html, body").animate({ scrollTop: "0" },1000)
        $("html, body").animate({ scrollTop: "1000" },1000)
    }
}, 2000); // 2000 = 2 x 1000

// reset do_scroll based on whatever condition.

This was a lot of fun.

Alexander Kleinhans
  • 5,950
  • 10
  • 55
  • 111