最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dynamically add and remove the div on scroll? - Stack Overflow

programmeradmin5浏览0评论

I tried to add and remove div tags while scrolling like the Dojo grid works. I only want to display 7 div tags.

While scrolling left inside the container, when the first div tag (on the left side) was hidden from the webpage, then that hidden div is removed from the container and a new one is attached onto the right side.

The same process should be applied while scrolling to the right.

It's similar to this example. But in stead of scrolling the <tr> tag, I want to scroll through <div>'s.

This is what I tried before: / How can I do it? If there's any plugin out there (like Dojo), it's also helpful.

I tried to add and remove div tags while scrolling like the Dojo grid works. I only want to display 7 div tags.

While scrolling left inside the container, when the first div tag (on the left side) was hidden from the webpage, then that hidden div is removed from the container and a new one is attached onto the right side.

The same process should be applied while scrolling to the right.

It's similar to this example. But in stead of scrolling the <tr> tag, I want to scroll through <div>'s.

This is what I tried before: https://jsfiddle/9y2ptsbg/3/ How can I do it? If there's any plugin out there (like Dojo), it's also helpful.

Share edited Apr 8, 2015 at 11:00 Dimitri Mestdagh 45k17 gold badges108 silver badges145 bronze badges asked Apr 1, 2015 at 10:43 user4284509user4284509 3
  • You actually do nothing related to appending divs in your onscroll function – Tien Nguyen Commented Apr 1, 2015 at 11:01
  • @TienNguyen I used for loop for appedning, this is not a gud idea.? – user4284509 Commented Apr 1, 2015 at 11:05
  • 1 it is not a problem. your foor loop executed only once. It means that you append divs only once. Look at this to grasp the problem. jsfiddle/mandarin6b0/9y2ptsbg/4 . You can continue from this point to solve your problem – Tien Nguyen Commented Apr 1, 2015 at 11:09
Add a ment  | 

4 Answers 4

Reset to default 1 +50

maybe this js fiddle would help ?
https://jsfiddle/9y2ptsbg/12/

var container = $("#container"),
info = $("#info");

var j = 0;
var colors = ['rgba(143, 146, 199, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)']

var ary = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36'],
cursor = 0,
attachDiv = function (_curr) {
container.empty();
var j = 0;

for (var i = _curr; i < _curr + 8; i++) {

    container.append('<div  class = "blocks blocks' + i + '" style="left:' +   (j * 25) + '%; background:' + colors[i] + ';">' + ary[i] + '</div>');
    j++;
}
};
var hasScrolled = false,
locked = false,
ticker = function () {
    if (hasScrolled && !locked) {
        locked = true;
        var xz = container.scrollLeft(),
            maxScrollLeft = container.get(0).scrollWidth - container.get(0).clientWidth,
            middle = maxScrollLeft / 2;
        if (xz == 0) {
            cursor = Math.max(0, cursor - 4);
        } else if (xz == maxScrollLeft) {
            cursor = Math.min(cursor + 4, ary.length - 8)
        }
        attachDiv(cursor);
        container.scrollLeft(middle);
        info.text(cursor);
        locked = false;
    }
    hasScrolled = false;
}
setInterval(ticker, 250);
    container.on('scroll', function () {
    hasScrolled = true;
});

attachDiv(0);

Yes it's possible. First of all, you will need something like this as structure:

<div class="scroll">
    <div class="container">
        <div class="element element-1">1</div>
        <div class="element element-2">2</div>
        <div class="element element-3">3</div>
        <div class="element element-4">4</div>
        <div class="element element-5">5</div>
        <div class="element element-6">6</div>
    </div>
</div>

The .scroll element will be your scrolling container, it's limited in either width or height (depending on how you want to scroll) and has an overflow.

The .container on the other hands takes the highest possible width, so for 6 elements it would be element width * 6.

Finally, because you want to create a left/right scrolling animation, you probably want to set float: left to all .element nodes.

The JavaScript code isn't hard either. You want to add an onScroll event handler to the .scroll element, you can do that like this:

query(".scroll").on("scroll", function(evt) {

});

Then you want to detect whether or not you're scrolling to the left or right. You can do that by paring the scrolling offset to the previous scrolling offset, for example:

if (lastPos && lastPos - evt.target.scrollLeft > 0) {
    // Scrolling to the left
} else if (lastPos && lastPos - evt.target.scrollLeft < 0) {
    // Scrolling to the right
}
lastPos = evt.target.scrollLeft;

Now, inside the if, you want to loop over all your .element's, detect whether or not on the left- or rightside of the visible portion, and if it is on one of those sides, you move it to the other side (depending on the scrolling direction).

To check whether or not the element is on the left- or right-side of the .scroll, I'm using Element.getBoundingClientRect():

var isLeftOfContainer = function(element) {
    var bounds = element.getBoundingClientRect();
    return (-bounds.left + element.parentNode.offsetLeft) >= bounds.width;
};

var isRightOfContainer = function(element) {
    var bounds = element.getBoundingClientRect();
    var box = element.parentNode.parentNode.getBoundingClientRect();
    return bounds.left - element.parentNode.offsetLeft > box.width;
};

To move the node to the other side, I'm using dojo/dom-construct::place(). You can add either "first" or "last" as third parameter, depending on the direction you're scrolling, for example:

domConstruct.place(elem, elem.parentNode, "first");

This will move the element (elem) to the first position of the parent node. Which is the thing we want to do when we're scrolling to the left.

To loop over all elements you can use dojo/query, for example:

query(".element").forEach(function(element) {

});

Remember that when you're scrolling to the left, you want to loop through the array from the last element to the first element, so that if 2 elements got hidden at the same time, the 6th element is added as first element before adding the 5th element as first element. This ensures that you always add the elements in the right order.

Then finally you have to adjust the scrolling position of the .scroll element. If you move a DOM node to the other side of the list, it has a side effect that all elements will move. This will lead to weird/buggy behavior if you don't move back the scrolling position.

You can do that by adjusting the scrollLeft attribute of the .scroll element.

Everything bined you could e up with something like this: http://jsfiddle/c3u6bfmf/

Try

$(function() {
          
  // adjust `colors` length to multiples of 7
  var colors = [
    "rgba(143, 146, 199, 0.49)",
    "rgba(199, 143, 186, 0.49)",
    "rgba(149, 199, 143, 0.49)",
    "rgba(229, 86, 61, 0.49)",
    "rgba(212, 229, 61, 0.49)",
    "rgba(206, 61, 229, 0.49)",
    "rgba(229, 157, 61, 0.49)",
    "rgba(61, 165, 229, 0.49)",
    "rgba(61, 229, 133, 0.49)",
    "rgba(229, 61, 61, 0.49)",
    "rgba(116, 61, 229, 0.49",
    "rgba(218, 229, 61, 0.49)",
    "rgba(21, 43, 157, 0.49)",
    "rgba(153, 157, 21, 0.49)",
    "rgba(199, 143, 186, 0.49)",
    "rgba(149, 199, 143, 0.49)",
    "rgba(229, 86, 61, 0.49)",
    "rgba(212, 229, 61, 0.49)",
    "rgba(206, 61, 229, 0.49)",
    "rgba(229, 157, 61, 0.49)",
    "rgba(61, 165, 229, 0.49)",
    "rgba(61, 229, 133, 0.49)",
    "rgba(229, 61, 61, 0.49)",
    "rgba(116, 61, 229, 0.49",
    "rgba(218, 229, 61, 0.49)",
    "rgba(21, 43, 157, 0.49)",
    "rgba(153, 157, 21, 0.49)",
    "rgba(199, 143, 186, 0.49)"
    // "rgba(149, 199, 143, 0.49)"
  ];
  
  var container = $("<div/>", {
    "id":"container",
    "title":"click to pause , resume `scroller`"
  });
  
  var n = 7;

  var scrolled = false;

  var elems = $.map(colors, function(color, i) {
    return $("<div>", {
      "class": "blocks-" + (i + 1),
      "text": i + 1,
      "css": {
        "backgroundColor": color,
        "left": (i * 25) + "%"
      }
    })[0].outerHTML
  });
  
  var scroller = function scroller(e) {

    var xz = container.scrollLeft();
    
    var wx = container.width() * .73;
    
    var keys = $.map($("div:first, div:last", container), function(el) {
      return Number(el.className.replace(/[^\d+]/g, ""));
    });
    
    var first = keys[0];
    
    var last = keys[1];
    
    var _scroller = function _scroller(elem, idx) {

      if (idx === 1 && scrolled) {
        scrolled = false;
        elem.scroll()
        return
      };
      
      elem
      .stop(true, true)
      .off("scroll")
      .empty()
      .append(
        elems
        .slice(idx ? (idx - 1) - n : last
               , idx ? idx - 1 : last + n)
        .map(function(el, i) {
           return $(el).css("left", (i * 25) + "%")[0].outerHTML
        }).join("")
      )
      .delay(250)
      .animate({
          scrollLeft: (idx ? "+=" : "-=") + elem.width() / 3
        }, 1000, function() {
            scrolled = true;
            elem.on("scroll", scroller).scroll()
      })      
    };
        
    if (xz < n && first !== 1 ) {
      _scroller(container, first)
    };
    
    if (xz > wx && last !== colors.length) {              
       _scroller(container);   
    };
    


  };

  $("body")
  .append(
    container.data("scroll", true).html(elems.slice(0, n))
    .on("scroll", scroller)
  );
  
  container.on("click", function() {
     if (container.data("scroll")) {
       container.data("scroll", false).off("scroll")
     } else {
       container.data("scroll", true)
       .on("scroll", scroller).scroll()
     }
  })

});
[class^=blocks] {
  padding: 0px;
  width: 25%;
  position: absolute;
  height: 150%;
  text-align: center;
  font-size: 100px;
}
#container {
  width: 100%;
  height: 250px;
  position: relative;
  overflow: auto;
  margin-top: 50%;
  background: #2a2a2a;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js">
</script>

Actually in the example you have given you are scrolling through divs. Each div contains a table, but that's beside the point.

I would say you need one content div, and play with its margins in javascript according to current scroll position. Just make sure the total width remains the same.

This would ensure the standard scrollbar is shown correctly and doesn't "jump", while the content can be adjusted to its position.

In the example you provided, BTW, they use 3 divs with partial content - only the div or divs in display have content, and perhaps partial content (only some content on its bottom or top, enough to fill the displayed area).

Anyway, the key here is to maintain a scrollable element large enough for the scrollbar to maintain its size and position, or to use a custom scrollbar written pletely in javascript.

发布评论

评论列表(0)

  1. 暂无评论