XiOXiS
XiOXiS

Reputation: 33

Autoscrolling list of items

I have a list of items in a div and the outer div have a fixed height. So the items are overflowed but hidden inside the outer div. I want to scroll the outer div until the last item in the list is visible. I am half way there. I scrolled the outer div until the last list item.


This is what I have done so far:

$(document).ready(function() {

  $m = $('.marq');
  $q = $('.qbox');
  var mh = $m.height();
  var qh = $q.height();
  var currscr = 0;
  scroll();

  function scroll() {

    var xpx = mh - qh;
    if (mh > qh) {
      currscr = xpx;
      setInterval(function() {
        autoscroll();
      }, 50);

    } else {
      console.log("too few items");
    }
  }

  function autoscroll() {

    if (currscr > 0) {
      var ch = $m.css('top').replace('px', '');
      $m.css('top', (ch - 1) + 'px');
      --currscr;
    }

  }



});
.qbox {
  height: 90vh;
  width: 80vw;
  box-sizing: border-box;
  overflow: hidden;
}

.marq {
  position: relative;
  box-sizing: border-box;
}

.item {
  background: #4CAF50;
  color: white;
  box-sizing: border-box;
  padding: 5px;
  margin-bottom: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="qbox">
  <div class="marq">

    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    <div class="item">Item 8</div>
    <div class="item">Item 9</div>
    <div class="item">Item 10</div>
    <div class="item">Item 11</div>
    <div class="item">Item 12</div>
    <div class="item">Item 13</div>
    <div class="item">Item 14</div>
    <div class="item">Item 15</div>


  </div>
</div>

It stops on reaching the last item. I want it to scroll back to the first item after some delay. Then scroll to bottom after some delay. And repeat this infinitely.

NOTE: The speed should be consistent and the number of items in the list should not affect the speed of scroll. This is applicable to both scroll, top to bottom and bottom to top. The scroll animation should be more linear-like.

Any help?

Upvotes: 2

Views: 2443

Answers (2)

ReSedano
ReSedano

Reputation: 5060

You were almost at the end!

I created 3 variables:

var interval; /* this is to put your setInterval */
var waitingTimeBottom = 2000; /* This is waiting time when you arrive at the bottom */
var waitingTimeTop =5000 /* This is waiting time on top */

Then put your setInterval in that variable on scroll() function:

interval=setInterval(function() {
    autoscroll();
}, 50);

After that I worked only in the end of autoscroll() function adding the 2 delay that you requested:

else {
    clearInterval(interval);
    $m.delay(waitingTimeBottom).animate({'top': '0px'}, 2000, function() {
        setTimeout(function()  {
            scroll();
        }, waitingTimeTop);
    });
}

This is all code in action:

$(document).ready(function() {

    $m = $('.marq');
    $q = $('.qbox');
    var mh = $m.height();
    var qh = $q.height();
    var currscr = 0;

    var interval;
    var waitingTimeBottom = 2000;
    var waitingTimeTop = 5000

    scroll();

    function scroll() {

        var xpx = mh - qh;
        if (mh > qh) {
            currscr = xpx;

            interval = setInterval(function() {
                autoscroll();
            }, 50);

        } else {
            console.log("too few items");
        }
    }

    function autoscroll() {

        if (currscr > 0) {
            var ch = $m.css('top').replace('px', '');
            $m.css('top', (ch - 1) + 'px');
            --currscr;
        } else {
            clearInterval(interval);
            $m.delay(waitingTimeBottom).animate({
                'top': '0px'
            }, 2000, function() {
                setTimeout(function() {
                    scroll();
                }, waitingTimeTop);
            });
        }
    }

});
.qbox {
  height: 90vh;
  width: 80vw;
  box-sizing: border-box;
  overflow: hidden;
}

.marq {
  position: relative;
  box-sizing: border-box;
}

.item {
  background: #4CAF50;
  color: white;
  box-sizing: border-box;
  padding: 5px;
  margin-bottom: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="qbox">
  <div class="marq">

    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    <div class="item">Item 8</div>
    <div class="item">Item 9</div>
    <div class="item">Item 10</div>
    <div class="item">Item 11</div>
    <div class="item">Item 12</div>
    <div class="item">Item 13</div>
    <div class="item">Item 14</div>
    <div class="item">Item 15</div>


  </div>
</div>

Edit 1

I changed a little your JavaScript using 2 more simple animations with a linear speed:

$(document).ready(function () {

	$m = $('.marq');
	$q = $('.qbox');
	var mh = $m.height();
	var qh = $q.height();

	var xpx = mh - qh;

	var waitingTimeBottom = 2000;
	var waitingTimeTop = 5000;
	var animationTime = xpx * 20; /* Here you can change the speed: if you use "xpx" variable, it never changes according to the number of items => change only the duration, not the speed. */

	function scroll() {
		$m.animate({'top': -xpx + "px"}, animationTime, "linear", function () {
			$m.delay(waitingTimeBottom).animate({'top': '0px'}, animationTime, "linear", function () {
				setTimeout(function () {
					scroll();
				}, waitingTimeTop);
			});
		});
	}


	if (mh > qh) {
		scroll();
	} else {
		console.log("too few items");
	}

});
.qbox {
  height: 90vh;
  width: 80vw;
  box-sizing: border-box;
  overflow: hidden;
}

.marq {
  position: relative;
  box-sizing: border-box;
}

.item {
  background: #4CAF50;
  color: white;
  box-sizing: border-box;
  padding: 5px;
  margin-bottom: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="qbox">
  <div class="marq">

    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    <div class="item">Item 8</div>
    <div class="item">Item 9</div>
    <div class="item">Item 10</div>
    <div class="item">Item 11</div>
    <div class="item">Item 12</div>
    <div class="item">Item 13</div>
    <div class="item">Item 14</div>
    <div class="item">Item 15</div>


  </div>
</div>

Upvotes: 1

Bryan
Bryan

Reputation: 133

var scroller = document.getElementById('scroller');
var scroller_height = scroller.clientHeight;
var qbox_height = document.getElementById('qbox').clientHeight;

function scrollForever(p_top)
	{
	var move_distance = 1;
	var new_top = p_top - move_distance;
	scroller.style.top = ""+p_top+"px";
	if(scroller_height+(new_top-qbox_height)>=0)
		{
		setTimeout(function(){scrollForever(new_top)},50);
		}
	else
		{
		setTimeout(function(){scrollBack(new_top)},1000);
		}
	}
function scrollBack(p_top)
	{
	var move_distance=1;
	if(p_top<0)
		{
		p_top = p_top+move_distance;
		scroller.style.top = ""+p_top+"px";
		setTimeout(function(){scrollBack(p_top)},50);
		}
	else
		{
		scroller.style.top = "0px";
		setTimeout(function(){scrollForever(0)},1000);
		}
	}
scrollForever(0);
<!DOCTYPE html>
<html>

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>scrolling.html</title>
<style type="text/css">

.qbox {
  height: 175px;
  width: 500px;
  box-sizing: border-box;
  overflow: hidden;
}

.marq {
  position: relative;
  box-sizing: border-box;
}

.item {
  background: #4CAF50;
  color: white;
  box-sizing: border-box;
  padding: 5px;
  margin-bottom: 8px;
}

</style>
</head>

<body>

<div class="qbox" id="qbox">
  <div class="marq" id="scroller">

    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    <div class="item">Item 8</div>
    <div class="item">Item 9</div>
    <div class="item">Item 10</div>
    <div class="item">Item 11</div>
    <div class="item">Item 12</div>
    <div class="item">Item 13</div>
    <div class="item">Item 14</div>
    <div class="item">Item 15</div>


  </div>
</div>
</body>

</html>
Here is the update that does what you want. Cheers!!

Upvotes: 1

Related Questions