如何在jQuery中创建垂直滚动的div?

时间:2019-04-26 18:33:13

标签: javascript jquery html css

我正在使用带有动画的jquery创建垂直自动滚动div ...我已经完成了创建,但是唯一的问题是当我向下滚动窗口到div滚动的列表div的中间时,它将窗口向上推到滚动列表div。我不知道问题是什么。但是,当我尝试以像素为单位指定列表div宽度时,它并没有增加...

尝试向下滚动到滚动列表div的中间。您将了解问题所在。谢谢...

setInterval(function(){
  $('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
    $(this).scrollTop(0).find('div:last').after($('div:first', this));
  });
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#list {
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="list">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
  <div>Item 5</div>
  <div>Item 6</div>
  <div>Item 7</div>
  <div>Item 8</div>
  <div>Item 9</div>
  <div>Item 10</div>   
</div>

2 个答案:

答案 0 :(得分:2)

真是个奇怪的错误。据我所知,由于第一个元素的removal/insertion到列表的末尾,这导致Chrome重新渲染列表,导致scrollY偏移量发生变化。

我个人可以想到两种解决问题的方法。

1)从DOM流中删除div(#list)。

注意:这需要将#list元素包装在containing元素中。

由于将删除/附加元素添加到#list元素中,因此导致发生重排(???)。最初,我认为使用position: absolute可以解决此问题,因为您不再影响DOM流。但是,即使position: absolute仍会导致滚动位置跳转。

然后,我查看了position: fixed,它确实起作用(因为它基本上位于所有内容的顶部)-显然,这不起作用,因为您希望列表随页面一起滚动!那么,我们如何解决这个问题?

transform来营救!

让我们利用transform quirk!通常,当元素为position: fixed时,它是相对于视口的。但是,如果祖先元素具有transformation,则位于fixed的元素将相对于转换后的元素。让我们试一下吧!

正如我提到的,您需要应用包装/包含元素进行转换。在下面的代码段中,我用新的#list包裹了您的div#transformed元素。

CSS更改很简单,看起来像:

#transformed { transform: translateZ(0); }
#list { position: fixed; }

就是这样!请查看下面的代码片段,以查看实际效果。

setInterval(function(){
  $('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
    $(this).find('div:last').after($('div:first', this));
  });
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>   
  </div>
</div>

2)滑动图层

关于解决该问题的第二种方法,这更多地是关于如何解决此问题的讨论/意见(因此,很遗憾无法提供代码)。

我不是操纵scrollTop,而是研究一种“滑动”层方法(使用transformYtop)。

您会发现基于JS的轮播采用类似的方法(很有趣,轮播倾向于使用滚动偏移方法-类似于此问题,或者是“滑动”层方法!他们只是倾向于这样做水平)

对于您要操纵的层,我再次建议将其从DOM流中删除(因此position: absolute)。从理论上讲,操纵该层不应影响滚动偏移量。

无论如何,希望这对您有所帮助,position: fixed方法对您有用:)

编辑

关于您的评论,您可以通过反转setInterval逻辑来实现“向下”滚动。但是,除了滚动然后将刚刚滚动到列表底部的项目移动到列表底部之外,您需要将要滚动到其中的元素移到列表顶部,使scrollTop偏移,然后滚动。 / p>

这是一个演示以下内容的代码段:

setInterval(function(){
    $('#list')
        .find('div:first')
        .before($('div:last', '#list'))
        .end()
        .scrollTop(40)
        .stop()
    .animate({scrollTop:0}, 400, 'swing');
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>
  </div>
</div>

编辑#2:

关于上/下按钮,通过组合到目前为止我们编写的两个脚本,您可以轻松实现这一目标!这是两个单击时会向上/向下动画的片段(第一个片段将在您每次单击时滚动,第二个片段将更改动画方向):

function animateList(direction) {
if (direction === 'down') {
    $('#list')
        .find('div:first')
        .before($('div:last', '#list'))
        .end()
        .scrollTop(40)
        .stop()
        .animate({scrollTop:0}, 400, 'swing');
} else {
    $('#list')
        .animate({scrollTop:40}, 400, 'swing', function(){
            $(this)
                .find('div:last')
                .after($('div:first', this));
        });
}
}

$('button').on('click', function () {
var direction = $(this).attr('id');
animateList(direction);
});
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>
  </div>
</div>

<button id="up">Scroll Up</button>
<button id="down">Scroll Down</button>

以及更改方向的代码段:

var interval;
function animateList(direction) {
    // Reset interval
    if (interval) {
        clearInterval(interval);
    }
    if (direction === 'down') {
        interval = setInterval(function () {
            $('#list')
                .find('div:first')
                .before($('div:last', '#list'))
                .end()
                .scrollTop(40)
                .stop()
                .animate({scrollTop:0}, 400, 'swing');
        }, 1000);
    } else {
        interval = setInterval(function () {
            $('#list')
                .animate({scrollTop:40}, 400, 'swing', function(){
                    $(this)
                        .find('div:last')
                        .after($('div:first', this));
                });

        }, 1000);
    }
}
$('button').on('click', function () {
    var direction = $(this).attr('id');
    animateList(direction);
});

// Initial animation
animateList('up');
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>
  </div>
</div>

<button id="up">Scroll Up</button>
<button id="down">Scroll Down</button>

答案 1 :(得分:1)

我已将您的内部div转换为无序列表。最初,我添加了一个overflow-y:scroll,但也可以使用,但是在看到您的评论后将其更改为overflow-y:hidden。我找到了,但是都可以。如果您向下滚动页面然后向上滚动,则它不会“重新开始”(除非有时间遍历所有10个列表项)。您可能需要调整css / box的高度,以在底部显示红色边框,但我会留给您

希望这会有所帮助

隐藏的流量:

setInterval(function() {
  $('#ulList').stop().animate({
    scrollTop: 40
  }, 400, 'swing', function() {
    $(this).scrollTop(0).find('li:last').after($('li:first', this));
  });
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#list {
  overflow-y:hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list ul {
  margin: 10px 10px;
  padding: 10px 0px;
}

#list ul li {
  display: block;
  height: 30px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
  <ul id="ulList">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    <li>Item 7</li>
    <li>Item 8</li>
    <li>Item 9</li>
    <li>Item 10</li>
  </ul>

</div>

溢出:滚动

setInterval(function() {
  $('#ulList').stop().animate({
    scrollTop: 40
  }, 400, 'swing', function() {
    $(this).scrollTop(0).find('li:last').after($('li:first', this));
  });
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#list {
  overflow-y:scroll;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list ul {
  margin: 10px 10px;
  padding: 10px 0px;
}

#list ul li {
  display: block;
  height: 30px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
  <ul id="ulList">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    <li>Item 7</li>
    <li>Item 8</li>
    <li>Item 9</li>
    <li>Item 10</li>
  </ul>

</div>