复杂的连续滚动循环

9

我有一个类似于以下代码:

<div id='right-column'>
    <div id='results'>
        <div id='result1>
            <div class='main'></div>
            <div class='details'></div>
        </div>
        <!-- ... -->
        <div id='result50>
            <div class='main'></div>
            <div class='details'></div>
        </div>
    </div>
</div>
  • 结果的总数取决于ajax查询,我一次性将所有结果动态插入。
  • div.main始终可见(固定高度),当用户单击result div时,在div.main下方“展开/折叠”div.details
  • details div的高度可能会有所变化。

如果#resultsscrollHeight大于#right-columnheight,我希望创建一个连续的滚动循环。
在这种情况下,向下滚动#result50将显示#result1,向上滚动#result1将显示#result50

我不能像在某些情况下一样将第一个子元素附加到底部,因为在列的顶部和底部可能会看到部分result的内容。
我不能复制result,除非我检测到是否展开/折叠了.details
当用户展开.details div时,result的高度会发生变化,这使得问题更加复杂......

以下是连续滚动循环的示例(2列):

$(document).ready(function() {
  var num_children = $('#up-left').children().length;
  var child_height = $('#up-left').height() / num_children;
  var half_way = num_children * child_height / 2;
  $(window).scrollTop(half_way);

  function crisscross() {
    $('#up-left').css('bottom', '-' + window.scrollY + 'px');
    $('#down-right').css('bottom', '-' + window.scrollY + 'px');
    var firstLeft = $('#up-left').children().first();
    var lastLeft = $('#up-left').children().last();
    var lastRight = $('#down-right').children().last();
    var firstRight = $('#down-right').children().first();

    if (window.scrollY > half_way ) {
      $(window).scrollTop(half_way - child_height);
      lastRight.appendTo('#up-left');
      firstLeft.prependTo('#down-right');
    } else if (window.scrollY < half_way - child_height) {
      $(window).scrollTop(half_way);
      lastLeft.appendTo('#down-right');
      firstRight.prependTo('#up-left');
    }
  }

  $(window).scroll(crisscross);
});
div#content {
  width: 100%;
  height: 100%;
  position: absolute;
  top:0;
  right:0;
  bottom:0;
  left:0;
}
#box {
  position: relative;
  vertical-align:top;
  width: 100%;
  height: 200px;
  margin: 0;
  padding: 0;
}
#up-left {
  position:absolute;
  z-index:4px;
  left: 0;
  top: 0px;
  width: 50%;
  margin: 0;
  padding: 0;
}
#down-right {
  position:fixed;
  bottom: 0px;
  z-index: 5px;
  left: 50%;
  width: 50%;
  margin: 0;
  padding: 0;
}
h1 {margin: 0;padding: 0;color:#fff}
.black {background: black;}
.white {background: grey;}
.green {background: green;}
.brown {background: brown;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>

<div id="content">
  <div id="up-left">
    <div id="box" class="brown">
      <h1>ONE</h1>
    </div>
    <div id="box" class="black">
      <h1>TWO</h1>
    </div>
    <div id="box" class="white">
      <h1>THREE</h1>
    </div>
    <div id="box" class="black">
      <h1>FOUR</h1>
    </div>
    <div id="box" class="white">
      <h1>FIVE</h1>
    </div>
    <div id="box" class="black">
      <h1>SIX</h1>
    </div>
  </div><!-- #up-left -->
  <div id="down-right">
    <div id="box" class="white">
      <h1>SIX</h1>
    </div>
    <div id="box" class="black">
      <h1>FIVE</h1>
    </div>
    <div id="box" class="white">
      <h1>FOUR</h1>
    </div>
    <div id="box" class="black">
      <h1>THREE</h1>
    </div>
    <div id="box" class="white">
      <h1>TWO</h1>
    </div>
    <div id="box" class="green">
      <h1>ONE</h1>
    </div>
  </div><!-- #down-right -->
</div><!-- .content -->
(fiddle: http://jsfiddle.net/franckl/wszg1d6c/)

有没有任何提示/想法,我如何实现它?

我认为你要找的是叫做 AJAX 分页的东西。 - SaidbakR
这不是具有AJAX分页的无限滚动,我确实需要一个有限结果数量的循环。 - Franckl
我的想法是复制#results,即结果的整个列表。如果你向下滚动,就将它追加到后面;如果你向上滚动,就将它插入到前面。 - jeremy castelli
1个回答

2

根据滚动方向将项目移动到顶部或底部

您可以使用jQuery的.append().prepend()在不克隆它们的情况下移动项目。

您将使用类似于惰性加载(AJAX)无限滚动的技术,但在这种情况下,您希望处理向上滚动和向下滚动,并且与其从服务器加载新内容,您只需在列表中回收现有的DOM元素。

以下我演示了一种技术。 我将滚动位置存储在元素的.data缓存中,以便在检测滚动方向时轻松检索。 我选择检测滚动方向以避免提前进行不必要的变量分配来提高性能。否则,您将在不会发生该方向的滚动事件上获取元素并执行数学运算。

滚动处理程序:

$('#right-column').on('scroll', function (e) {
    var $this = $(this),
        $results = $("#results"),
        scrollPosition = $this.scrollTop();

    if (scrollPosition > ($this.data('scroll-position') || 0)) {
        // Scrolling down
        var threshold = $results.height() - $this.height() - $('.result:last-child').height();

        if (scrollPosition > threshold) {
            var $firstResult = $('.result:first-child');
            $results.append($firstResult);
            scrollPosition -= $firstResult.height();
            $this.scrollTop(scrollPosition);
        }
    } else {
        // Scrolling up
        var threshold = $('.result:first-child').height();
        if (scrollPosition < threshold) {
            var $lastResult = $('.result:last-child');
            $results.prepend($lastResult);
            scrollPosition += $lastResult.height();
            $this.scrollTop(scrollPosition);
        }
    }
    $this.data('scroll-position', scrollPosition)
});

一个完整的工作示例:

$('#right-column').on('scroll', function (e) {
    var $this = $(this),
        $results = $("#results"),
        scrollPosition = $this.scrollTop();

    if (scrollPosition > ($this.data('scroll-position') || 0)) {
        // Scrolling down
        var threshold = $results.height() - $this.height() - $('.result:last-child').height();
      
       if (scrollPosition > threshold) {
           var $firstResult = $('.result:first-child');
            $results.append($firstResult);
           scrollPosition -= $firstResult.height();
            $this.scrollTop(scrollPosition);
        }
    } else {
        // Scrolling up
        var threshold = $('.result:first-child').height();
        if (scrollPosition < threshold) {
            var $lastResult = $('.result:last-child');
            $results.prepend($lastResult);
           scrollPosition += $lastResult.height();
            $this.scrollTop(scrollPosition);
        }
    }
   $this.data('scroll-position', scrollPosition)
});

$('#results').on('click', '.result', function (e) {
   $(this).find('.details').toggle();
});

$('#newNumber').on('input', function (e) {
    var results = '';
    for (var n = 1; n <= $(this).val(); n++) {
        results += 
          '<div class="result" id="result' + n + '">' +
          '    <div class="main">Result ' + n + '</div>' +
          '    <div class="details">Details for result ' + n + '</div>' +
          '</div>';
    }
   $('#results').html(results);
});
body {
  font-family: sans-serif;
}
h1 {
  font: bold 2rem/1 Georgia, serif;
}
p {
  line-height: 1.5;
  margin-bottom: 1em;
}
label {
  font-weight: bold;
  margin-bottom: 1em;
}
.column {
  box-sizing: border-box;
  float: left;
  width: 50%;
  height: 100vh;
  padding: 1em;
  overflow: auto;
}
#right-column {
  background-color: LemonChiffon;
}
.result {
  padding: 1em;
  cursor: pointer;
}
.result .main {
  height: 2em;
  font-weight: bold;
  line-height: 2;
}
.result .details {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class=
"column" id="left-column">
  <p>Existing DOM elements are moved to the top or bottom of the list depending on your scroll direction.</p>
  <label>Change the number of results to display
    <input id="newNumber" type="number" value="10" />
</div>
<div class=
"column" id="right-column">
  <div id="results">
    <div id="result1" class="result">
      <div class="main">Result 1</div>
      <div class="details">Details for result 1</div>
    </div>
    <div id="result2" class="result">
      <div class="main">Result 2</div>
      <div class="details">Details for result 2</div>
    </div>
    <div id="result3" class="result">
      <div class="main">Result 3</div>
      <div class="details">Details for result 3</div>
    </div>
    <div id="result4" class="result">
      <div class="main">Result 4</div>
      <div class="details">Details for result 4</div>
    </div>
    <div id="result5" class="result">
      <div class="main">Result 5</div>
      <div class="details">Details for result 5</div>
    </div>
    <div id="result6" class="result">
      <div class="main">Result 6</div>
      <div class="details">Details for result 6</div>
    </div>
    <div id="result7" class="result">
      <div class="main">Result 7</div>
      <div class="details">Details for result 7</div>
    </div>
    <div id="result8" class="result">
      <div class="main">Result 8</div>
      <div class="details">Details for result 8</div>
    </div>
    <div id="result9" class="result">
      <div class="main">Result 9</div>
      <div class="details">Details for result 9</div>
    </div>
    <div id="result10" class="result">
      <div class="main">Result 10</div>
      <div class="details">Details for result 10</div>
    </div>
  </div>
</div>

在CodePen上有一个完整的工作示例,如果您喜欢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接