在滚动时动态添加和删除 div?

Posted

技术标签:

【中文标题】在滚动时动态添加和删除 div?【英文标题】:Dynamically add and remove the div on scroll? 【发布时间】:2015-04-01 10:43:57 【问题描述】:

我尝试在像 Dojo 网格一样滚动时添加和删除 div 标签。我只想显示 7 个 div 标签。

在容器内向左滚动时,当第一个 div 标签(左侧)从网页中隐藏时,该隐藏的 div 将从容器中移除,并在右侧附加一个新标签。

向右滚动时应应用相同的过程。

类似于this example。但我不想滚动 <tr> 标签,而是滚动浏览 <div> 的标签。

这是我之前尝试过的:https://jsfiddle.net/9y2ptsbg/3/我该怎么做?如果有任何插件(如 Dojo),它也很有帮助。

【问题讨论】:

您实际上没有做任何与在 onscroll 函数中添加 div 相关的操作 @TienNguyen 我使用for loop 进行附加,这不是一个好主意。? 这不是问题。你的 for 循环只执行一次。这意味着您只附加 div 一次。看这个来把握问题。 jsfiddle.net/mandarin6b0/9y2ptsbg/4 。您可以从这里继续解决您的问题 【参考方案1】:

也许这个 js fiddle 会有所帮助?https://jsfiddle.net/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);

【讨论】:

您好,如何进行垂直滚动(上下)?【参考方案2】:

是的,这是可能的。首先,你需要这样的结构:

<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>

.scroll 元素将成为您的滚动容器,它的宽度或高度都受到限制(取决于您想要滚动的方式),并且有一个 overflow

另一方面,.container 采用尽可能高的宽度,因此对于 6 个元素,它将是 element width * 6

最后,因为你想创建一个左/右滚动动画,你可能想将float: left设置为所有.element节点。

javascript 代码也不难。您想将onScroll 事件处理程序添加到.scroll 元素,您可以这样做:

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

);

然后你想检测你是向左还是向右滚动。您可以通过将滚动偏移量与之前的滚动偏移量进行比较来做到这一点,例如:

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;

现在,在if 中,您想要遍历所有.element,检测是否在可见部分的左侧或右侧,如果它在其中一侧,您将其移动到另一侧(取决于滚动方向)。

要检查元素是在.scroll 的左侧还是右侧,我使用的是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;
;

要将节点移动到另一侧,我使用dojo/dom-construct::place()。您可以添加"first""last" 作为第三个参数,具体取决于您滚动的方向,例如:

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

这会将元素 (elem) 移动到父节点的第一个位置。这是我们向左滚动时想要做的事情。

要遍历所有元素,您可以使用dojo/query,例如:

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

);

请记住,当您向左滚动时,您希望从数组的最后一个元素循环到第一个元素,这样如果同时隐藏了 2 个元素,则将第 6 个元素添加为第一个元素在添加第 5 个元素作为第一个元素之前。这可确保您始终以正确的顺序添加元素。

最后你必须调整.scroll元素的滚动位置。如果将 DOM 节点移动到列表的另一侧,则会产生所有元素都会移动的副作用。如果您不移回滚动位置,这将导致奇怪/错误的行为。

您可以通过调整.scroll 元素的scrollLeft 属性来做到这一点。

所有东西结合起来,你可以想出这样的东西:http://jsfiddle.net/c3u6bfmf/

【讨论】:

谢谢。我想通过array 内容显示blocks。我将数据存储到数组中,例如["1","10",40",56" ...],然后通过数组元素创建 div 标签。该数组有超过 5000 个数据。所以我想通过dojo 显示数组元素。我该怎么办? 使用dojo/dom-construct,您还可以创建元素。因此,遍历您的数组并使用domConstruct.create() 创建元素。使用domConstruct.place(),您可以将新元素放到.container 上。不要忘记调整.containerwidth,因为它取决于里面的项目数。 看看***.com/a/688685/1915448。它有点过时了,但概念仍然相同(而不是dojo.create,您使用domConstruct.create【参考方案3】:

试试

$(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.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>

【讨论】:

感谢您的回答,您的回答对我非常有用。但无法看到某些块,例如在第一次滚动中我看不到 7th 块。我想停下来检查每个块。再次非常感谢您的回答:) @aja 查看更新后的帖子。通过单击#container,将单击事件添加到“暂停”、“恢复”scroller 处理程序。应该能够在第一个 click "pauses" scroller ,第二个 click "resumes" scroller 之后检查每个 .block 。将title 属性添加到#container 以通知click 功能;虽然title 属性,通知可以被删除。欢迎你:) 非常感谢您。很抱歉再次问你。我想显示像`dojo`这样的元素。但是当滚动到容器时您的脚本会显示,那时删除所有块(7)并添加新块(7)。但是我想通过从显示器中隐藏多少块来将块添加到容器中。比如Onscroll,先显示第6个blocks,那个时候显示6 7 8 9。再次感谢 @aja 不确定解释“例如,Onscroll,首先显示第 6 块,那时显示 6 7 8 9。”正确吗?请参阅,在原始帖子 “我尝试像 dojo 网格一样添加和删除 div 标签 onscroll。?”“我想显示仅有的 7 个 div 标签。” ?在dojotoolkit.org/documentation/tutorials/1.9/working_grid/demo/…,元素似乎被添加、删除、再次添加?是否要求删除 scroll 事件中的元素? 嗯好的。我想添加和删除 div 标签正是 dojo 网格。我问这个的原因是什么,在我的脚本中生成 40 laks 值,到时候会出现 40 laks div 标签,所以我的程序运行得很慢。我认为这种方法(道场网格)适合我的问题的原因。你能帮助我吗。?非常感谢您花时间为我服务。谢谢【参考方案4】:

实际上,在您给出的示例中,您正在滚动浏览divs。每个div 都包含一个表格,但这不是重点。

我会说你需要一个内容div,并根据当前滚动位置在javascript中使用它的边距。只要确保总宽度保持不变。

这将确保标准滚动条正确显示并且不会“跳跃”,同时可以将内容调整到其位置。

在您提供的示例中,顺便说一句,他们使用 3 个带有部分内容的 divs - 只有显示中的 divdivs 有内容,也许还有部分内容(只有底部或顶部的一些内容,足以填满显示区域)。

无论如何,这里的关键是保持一个足够大的可滚动元素以使滚动条保持其大小和位置,或者使用完全用 javascript 编写的自定义滚动条。

【讨论】:

以上是关于在滚动时动态添加和删除 div?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery .hasClass 和动态添加的类

wpf 动态添加滚动条

使用 alpine JS 动态添加和删除 DOM 元素

python测试开发django-166.jQuery 使用append()动态添加div元素

jquery在一个父div中动态添加子div,并在每个子div中显示这是当前第几个子div

动态添加/删除输入字段并在单独的 div 中预览字段值