14

how can i add an easing/animation/slowly moving to this function? At the moment it just jumps. Now it should move to the "anchor" with an animation.

<script type='text/javascript'>
        setTimeout("window.scrollBy(0,270);",3000);
</script>
Max
  • 516
  • 1
  • 5
  • 20
  • 5
    **Never** pass a string to `setInterval()` or `setTimeout()`. Doing so is as bad as using `eval()` and it results in unreadable and possibly insecure code as soon as you use variables since you need to insert them into the string instead of passing the actual variable. The proper solution is `setInterval(function() { /* your code *) }, msecs);`. The same applies to `setTimeout()`. If you just want to call a single function without any arguments, you can also pass the function name directly: `setInterval(someFunction, msecs);` (note that there are **no** `()` behind the function name) – ThiefMaster Aug 30 '12 at 14:40
  • Consider using some existing library for it. – ThiefMaster Aug 30 '12 at 14:40
  • this one sound good, but how can i add the time after how many seconds the page should scroll http://flesler.blogspot.se/2007/10/jqueryscrollto.html – Max Aug 30 '12 at 14:53

8 Answers8

42

also possible with plain javascript using request animation frame..

// first add raf shim
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

// main function
function scrollToY(scrollTargetY, speed, easing) {
    // scrollTargetY: the target scrollY property of the window
    // speed: time in pixels per second
    // easing: easing equation to use

    var scrollY = window.scrollY,
        scrollTargetY = scrollTargetY || 0,
        speed = speed || 2000,
        easing = easing || 'easeOutSine',
        currentTime = 0;

    // min time .1, max time .8 seconds
    var time = Math.max(.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, .8));

    // easing equations from https://github.com/danro/easing-js/blob/master/easing.js
    var PI_D2 = Math.PI / 2,
        easingEquations = {
            easeOutSine: function (pos) {
                return Math.sin(pos * (Math.PI / 2));
            },
            easeInOutSine: function (pos) {
                return (-0.5 * (Math.cos(Math.PI * pos) - 1));
            },
            easeInOutQuint: function (pos) {
                if ((pos /= 0.5) < 1) {
                    return 0.5 * Math.pow(pos, 5);
                }
                return 0.5 * (Math.pow((pos - 2), 5) + 2);
            }
        };

    // add animation loop
    function tick() {
        currentTime += 1 / 60;

        var p = currentTime / time;
        var t = easingEquations[easing](p);

        if (p < 1) {
            requestAnimFrame(tick);

            window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));
        } else {
            console.log('scroll done');
            window.scrollTo(0, scrollTargetY);
        }
    }

    // call it once to get started
    tick();
}

// scroll it!
scrollToY(0, 1500, 'easeInOutQuint');
shunryu111
  • 4,667
  • 4
  • 20
  • 15
  • This is a great answer and helped me visualize advanced techniques of using javascript to extend it's own core features. Thanks! – lakewood Dec 15 '15 at 16:06
  • For IE11 support, you may use `window.pageYOffset` instead of `window.scrollY`. – Beat Sprenger Jul 06 '17 at 14:43
  • Is it possible to use this with elements' .scrollTop property? I can't get it to work for me. – Julius Apr 02 '19 at 15:17
  • I wish I could upvote this 10 times, this is exactly what I was looking for! This can also be for `scrollBy(dY)` functionality if you calculate targetY as targetY = window.scrollY + offset – mlz7 Sep 04 '20 at 23:38
14

For anyone viewing this question in 2019: this can now be done natively by using

window.scrollBy({
    top: 0,
    left: 270,
    behavior: 'smooth'
});

This works in all major browsers except edge and safari. See https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy#Examples

xnim
  • 153
  • 1
  • 8
  • Keep in mind it does not work in IE/Edge: https://caniuse.com/#feat=mdn-api_scrolltooptions_behavior – burtek Sep 30 '19 at 07:45
9

Adapted from this answer:

function scrollBy(distance, duration) {

    var initialY = document.body.scrollTop;
    var y = initialY + distance;
    var baseY = (initialY + y) * 0.5;
    var difference = initialY - baseY;
    var startTime = performance.now();

    function step() {
        var normalizedTime = (performance.now() - startTime) / duration;
        if (normalizedTime > 1) normalizedTime = 1;

        window.scrollTo(0, baseY + difference * Math.cos(normalizedTime * Math.PI));
        if (normalizedTime < 1) window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
}

This should allow you to smoothly scroll by the specified distance.

Raslanove
  • 519
  • 8
  • 13
2

Another example with jQuery, uses the easing plugin for some nice effects:

http://tympanus.net/codrops/2010/06/02/smooth-vertical-or-horizontal-page-scrolling-with-jquery/

piatek
  • 376
  • 1
  • 6
2

got it myself. because of wordpress and the jquery.noConflict Mode i hade to modify the code:

<script type="text/javascript">
        (function($){
        $(document).ready(function(){
            setTimeout(function() {
            $('body').scrollTo( '300px', 2500 );
        }, 3000);
        });
        }(jQuery));
</script>

thanks for everybody!!!

Max
  • 516
  • 1
  • 5
  • 20
1

When using jQuery, you could easily use the .animate function.

Here's an example on how it should work.

MarcoK
  • 5,952
  • 2
  • 26
  • 40
1

This will Work, Assume you need to Smooth-scrolls to the top of the page.

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};
  • Will this ever finish? Basically, you're doing `c = c * 7/8` and it will never actually touch `0`, right? It will converge to `0` and it will probably eventually be rounded down to `0` by JS due to limited precision, but still. – elslooo Sep 17 '19 at 15:49
0

Using jQuery makes this much easier, perhaps with the scrollto plugin. http://flesler.blogspot.se/2007/10/jqueryscrollto.html

Consider a solution such:

<script type='text/javascript' src='js/jquery.1.7.2.min.js'></script>
<script type='text/javascript' src='js/jquery.scrollTo-min.js'></script>
<script type='text/javascript' src='js/jquery.easing.1.3.js'></script><!-- only for other easings than swing or linear -->
<script type='text/javascript'>
$(document).ready(function(){
    setTimeout(function() {
    $('html,body').scrollTo( {top:'30%', left:'0px'}, 800, {easing:'easeInBounce'} );
}, 3000);
});
</script>

Of course you need to dl the scripts.

See http://jsfiddle.net/7bFAF/2/ for a working example

jtheman
  • 7,211
  • 3
  • 24
  • 38
  • and how can i add the time, after how many seconds the page should scroll? – Max Aug 30 '12 at 14:44
  • using jQuery you could easily use timeout just as you suggested yourself for setting the delay, example: http://stackoverflow.com/questions/1836105/how-to-wait-5-seconds-with-jquery – jtheman Aug 30 '12 at 14:54
  • i tried this..but it does not work.`code` `code` – Max Aug 31 '12 at 07:59
  • @max the "elasout" easing is only defined on the demo page. Other easings but the default swing or linear versions you will need the easing plugin as my example above. also note I edited the function to use timeout() instead of delay() as delay() only works with native jQuery effects. Use timeout() is more general. – jtheman Aug 31 '12 at 12:24
  • i have no idea what i am doing wrong: this is my code from the head of my wordpress site: http://jsfiddle.net/Z2eyN/ – Max Sep 01 '12 at 08:46
  • The function is really nothing wrong with. Hovever the file "http://domain.de/wp-content/themes/intellicig/library/libs/js/jquery.scrollTo-1.4.3-min.js" Doesn't seem to be there... And for testing purpose try to remove the easing part completely (i suspect you don't want easeInBounce anyway?)... – jtheman Sep 01 '12 at 12:52
  • 1
    he has a problem with the document ready function. http://cl.ly/image/0X02160j2x0g http://cl.ly/image/0a0m1f3c0a3a – Max Sep 01 '12 at 15:15