Search code examples
javascriptdelayscrolltoanchor-scroll

How to smooth scroll to an anchor if a user hasn't scrolled in 5 seconds?


So basically, thanks to a solution I have found already on stackoverflow, I have gotten as far as creating a smooth scroll to an anchor after 5 seconds.

The bit that I can't seem to add to this is simply having this ONLY trigger if a user hasn't already scrolled within the 5 seconds as this can be an irritating experience.

I have experimented with trying to add .scrollTo() in various different ways and wrapping to whole thing in another function but apart from basic understanding and tweaking of Javascript I don't really have much knowledge.

Any help would be greatly appreciated.

<script type="text/javascript">
/*<![CDATA[*/

var zxcScrollTo={

 Scroll:function(o){
  var a=document.getElementById(o.AnchorID),ms=o.Animate,s=!document.body.scrollTop?[document.documentElement.scrollLeft,document.documentElement.scrollTop]:[document.body.scrollLeft,document.body.scrollTop];
  if (a){
   this.animate(this,s,this.pos(a),new Date(),typeof(ms)=='number'&&ms>0?ms:1000);
  }
 },

 animate:function(o,f,t,srt,mS){
  clearTimeout(o.to);
  var ms=new Date()-srt,x=(t[0]-f[0])/mS*ms+f[0],y=(t[1]-f[1])/mS*ms+f[1];
  if (isFinite(x)&&isFinite(y)){
   window.scrollTo(x,y);
  }
  if (ms<mS){
   o.to=setTimeout(function(){ o.animate(o,f,t,srt,mS); },10);
  }
  else {
   window.scrollTo(t[0],t[1]);
  }
 },

 pos:function(obj){
  var rtn=[0,0];
  while(obj){
   rtn[0]+=obj.offsetLeft;
   rtn[1]+=obj.offsetTop;
   obj=obj.offsetParent;
  }
  return rtn;
 }


}
setTimeout(function(){
  zxcScrollTo.Scroll({
   AnchorID:'anchor',
   Animate:2000
  });
 },5000);

/*]]>*/
</script>

ANSWER:

Many thanks to @ByteHamster.

This code will smooth scroll user to an ID tag after 5000ms but not trigger if user has already started scrolling:

<script type="text/javascript">

var zxcScrollTo={

 Scroll:function(o){
  var a=document.getElementById(o.AnchorID),ms=o.Animate,s=!document.body.scrollTop?[document.documentElement.scrollLeft,document.documentElement.scrollTop]:[document.body.scrollLeft,document.body.scrollTop];
  if (a){
   this.animate(this,s,this.pos(a),new Date(),typeof(ms)=='number'&&ms>0?ms:1000);
  }
 },

 animate:function(o,f,t,srt,mS){
  clearTimeout(o.to);
  var ms=new Date()-srt,x=(t[0]-f[0])/mS*ms+f[0],y=(t[1]-f[1])/mS*ms+f[1];
  if (isFinite(x)&&isFinite(y)){
   window.scrollTo(x,y);
  }
  if (ms<mS){
   o.to=setTimeout(function(){ o.animate(o,f,t,srt,mS); },10);
  }
  else {
   window.scrollTo(t[0],t[1]);
  }
 },

 pos:function(obj){
  var rtn=[0,0];
  while(obj){
   rtn[0]+=obj.offsetLeft;
   rtn[1]+=obj.offsetTop;
   obj=obj.offsetParent;
  }
  return rtn;
 }


}

var wasScrolled = false;

window.onscroll = function () {
   wasScrolled = true;

}

function doSmoothScrollToAnchor() {
    if (wasScrolled === false) {
        zxcScrollTo.Scroll({
            AnchorID: 'anchor',
            Animate: 2000
        });
    }
}

setTimeout(doSmoothScrollToAnchor, 5000);


</script>

Solution

  • // Set a variable that gets changed as soon as the user scrolls:
    var wasScrolled = false;
    window.onscroll = function () {
      wasScrolled = true;
    }
    
    // Before actually scrolling via Javascript, check if the page was scrolled manually:
    function doSmoothScrollToAnchor() {
        if(wasScrolled === false) {
            alert("Was not scrolled");
        } else {
            alert("The user scrolled manually");
        }
    }
    setTimeout(doSmoothScrollToAnchor, 3000);
    Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />
    Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />
    Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />
    Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />Text<br />